diff --git a/extras/docker/build_and_push.sh b/extras/docker/build_and_push.sh index 980087cfe5..91e6fa15e5 100755 --- a/extras/docker/build_and_push.sh +++ b/extras/docker/build_and_push.sh @@ -1,3 +1,3 @@ #!/bin/bash -docker build --rm=true --build-arg BRANCH="develop" --build-arg DB_PASS="pandora" -t pandorafms/pandorafms:7 . && \ +docker build --rm=true --pull --no-cache --build-arg BRANCH="develop" --build-arg DB_PASS="pandora" -t pandorafms/pandorafms:7 . && \ docker push pandorafms/pandorafms:7 diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index f640e5b2d9..8f29aa2b25 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.734-190425 +Version: 7.0NG.734-190513 Architecture: all Priority: optional Section: admin diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh index 0a44c4aa23..2ba8db8f02 100644 --- a/pandora_agents/unix/DEBIAN/make_deb_package.sh +++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.734-190425" +pandora_version="7.0NG.734-190513" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index 52d4899f18..3ccb533275 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -42,7 +42,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.734'; -use constant AGENT_BUILD => '190425'; +use constant AGENT_BUILD => '190513'; # Agent log default file size maximum and instances use constant DEFAULT_MAX_LOG_SIZE => 600000; diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index da0990a731..677208d4ce 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.734 -%define release 190425 +%define release 190513 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index 127fab8cd1..36ba7967c0 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.734 -%define release 190425 +%define release 190513 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer index d7ea96904b..5630750352 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.734" -PI_BUILD="190425" +PI_BUILD="190513" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/unix/plugins/inventory b/pandora_agents/unix/plugins/inventory index a6d9a8bc83..6ef6233d23 100755 --- a/pandora_agents/unix/plugins/inventory +++ b/pandora_agents/unix/plugins/inventory @@ -4,23 +4,44 @@ # Copyright (c) 2009 Artica Soluciones Tecnologicas S.L. # # inventory Generate a hardware/software inventory. -# +# # Sample usage: ./inventory [cpu] [ram] [video] [nic] [hd] [cdrom] [software] [init_services] [filesystem] [process] [users] # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# GNU General Public License for more details. # ############################################################################### use strict; use constant TSTAMP_FILE => '/tmp/pandora_inventory.tstamp'; +use Scalar::Util qw(looks_like_number); +use Data::Dumper; +# Set environment language to English +$ENV{"LANG"} = "en_US"; + +# Check AIX system +my $AIX=0; +my $system = `uname -a | awk '{print $1}'`; +if ($system =~ 'AIX') { + $AIX=1; +} + +sub is_enabled { + my $value = shift; + if ((defined ($value)) && looks_like_number($value) && ($value > 0)){ + # return true + return 1; + } + #return false + return 0; +} # Operation mode (LSHW or HWINFO) my $Mode; @@ -31,12 +52,12 @@ my $Separator; sub get_module_data ($$$$) { my ($name, $hwinfo, $keys, $modules) = @_; my %module; - - # Store keys + $Separator='\s+\*\-'; + # Store keys foreach my $key (@{$keys}) { push (@{$module{'_keys'}}, $key); } - + # Parse module data while (my $line = shift (@{$hwinfo})) { if ($line =~ /$Separator/) { @@ -46,7 +67,7 @@ sub get_module_data ($$$$) { foreach my $key (@{$keys}) { if ($line =~ /$key:\s+(.+)/) { $module{$key} = $1; - # Replace semicolon by comma to avoid parse errors + # Replace semicolon by comma to avoid parse errors $module{$key} =~ s/;/,/g; } } @@ -58,12 +79,65 @@ sub get_module_data ($$$$) { push (@{$modules->{$name}}, \%module); } +sub test_contain ($$) { + my ($value, $array)=@_; + if ( grep( /$value/, @{$array} ) ) { + return 1; + } +} +sub get_module_data_aix_ram_cpu ($$$$) { + my ($name, $hwinfo, $keys, $modules) = @_; + my %module; + # Store keys + foreach my $key (@{$keys}) { + push (@{$module{'_keys'}}, $key); + } + # Parse module data + foreach my $line (@{$hwinfo}) { + foreach my $key (@{$keys}) { + if ($line =~ /$key:\s+(.+)/) { + $module{$key} = $1; + $module{$key} =~ s/,/ /g; + } + } + } + + # No data found + #my @data = keys (%module); + #return unless ($#data >= 0); + + push (@{$modules->{$name}}, \%module); +} +sub get_module_data_aix ($$$$) { + my ($name,$hwinfo,$regex,$modules) = @_; + my %module; + foreach my $line (@{$hwinfo}) { + $line =~ s/\s{2,}/;/g; + $line =~ s/\+ //g; + $line =~ s/\* //g; + } + foreach my $line (@{$hwinfo}) { + if ($line =~ /$regex/){ + my ($var1, $var2, $var3) = split /;/, $line; + my %module; + $module{'device'} = $var1; + $module{'serial'} = $var2; + $module{'description'}=$var3; + $module{'_keys'} = ['device','serial','description']; + push (@{$modules->{$name}}, \%module); + } + } +} # Get a list of information file system in machine sub get_file_system($$) { my ($name, $modules) = @_; - - my @fileSystems = `df -hP | tail -n +2`; #remove the titles of columns + my @fileSystems; + if (is_enabled $AIX){ + @fileSystems = `df -gP | tail -n +2`; + } else { + @fileSystems = `df -hP | tail -n +2`; #remove the titles of columns + } foreach my $row (@fileSystems) { next unless ($row =~ /^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+\S+\s+(\S+)/); @@ -73,94 +147,110 @@ sub get_file_system($$) { $module{'used'} = $2; $module{'avail'} = $3; $module{'mount'} = $4; - $module{'_keys'} = ['filesystem', 'used','avail', 'mount']; - push (@{$modules->{$name}}, \%module); - } + $module{'_keys'} = ['filesystem', 'used','avail', 'mount']; + push (@{$modules->{$name}}, \%module); + } } # Get a list of services init in machine sub get_servicies_init_machine($$) { my ($name, $modules) = @_; - my $runlevel = `who -r | awk '{print \$2}'`; + my $runlevel; + if (is_enabled $AIX) { + $runlevel = `who -r | awk '{print \$3}'`; + } else { + $runlevel = `who -r | awk '{print \$2}'`; + } #ini trim($runlevel) $runlevel =~ s/^\s*//; #ltrim $runlevel =~ s/\s*$//; #rtrim #end trim($runlevel) - my $script = ""; - + my $script; + if (-e "/etc/rc" . $runlevel .".d/") { - $script = "ls /etc/rc" . $runlevel .".d/ -l | grep \"^l.*\" | awk \"{print \\\$NF}\" | sed -e \"s/\\.\\.\\///g\" | sed -e \"s/.*init\\.d\\///g\""; + $script = "ls -l /etc/rc" . $runlevel .".d/ | grep \"^l.*\" | awk \"{print \\\$NF}\" | sed -e \"s/\\.\\.\\///g\" | sed -e \"s/.*init\\.d\\///g\""; } else { - $script = "ls /etc/rc.d/rc" . $runlevel .".d/ -l | grep \"^l.*\" | grep \" S.* \" | awk \"{print \\\$NF}\" | sed -e \"s/\\.\\.\\///g\" | sed -e \"s/.*init\\.d\\///g\""; - + $script = "ls -l /etc/rc.d/rc" . $runlevel .".d/ | grep \"^l.*\" | grep \" S.* \" | awk \"{print \\\$NF}\" | sed -e \"s/\\.\\.\\///g\" | sed -e \"s/.*init\\.d\\///g\""; } - + my @services = `$script`; foreach my $row (@services) { - my %module; - $row =~ s/\n//; - $module{'service'} = $row; - $module{'_keys'} = ['service']; - push (@{$modules->{$name}}, \%module); + $row =~ s/\n//; + $module{'service'} = $row; + $module{'_keys'} = ['service']; + push (@{$modules->{$name}}, \%module); } } # Get a list of running processes sub get_processes ($$) { my ($name, $modules) = @_; + my $script; + if (is_enabled $AIX) { + $script = "ps -eo args | tail -n +2"; + } else { + $script = "ps -eo command | tail -n +2"; + } - my $script = "ps -eo command"; - - my @services = `$script`; - foreach my $row (@services) { - my %module; - # Remove carriage returns - $row =~ s/[\n\l\f]//g; - # Replace semicolon by comma to avoid parse errors - $row =~ s/;/,/g; - $module{'service'} = $row; - $module{'_keys'} = ['service']; - push (@{$modules->{$name}}, \%module); - } + my @services = `$script`; + foreach my $row (@services) { + my %module; + # Remove carriage returns + $row =~ s/[\n\l\f]//g; + # Replace semicolon by comma to avoid parse errors + $row =~ s/;/,/g; + $module{'service'} = $row; + $module{'_keys'} = ['service']; + push (@{$modules->{$name}}, \%module); + } } # Get a list of valid users in the system sub get_users ($$) { - my ($name, $modules) = @_; - - my $script = "cat /etc/passwd"; + my ($name, $modules) = @_; + my $script = "cat /etc/passwd"; my $user = ""; my $estado = ""; - my @services = `$script`; - foreach my $row (@services) { - my %module; + my @services = `$script`; + foreach my $row (@services) { + my %module; - next unless ($row =~ /^([A-Za-z0-9\-\_]*)/); - - $user = $1; - $script = `passwd -S $user`; - if ( $script =~ /^(\S+)\sP./){ - $module{'user'} = $user; - $module{'_keys'} = ['user']; - push (@{$modules->{$name}}, \%module); + next unless ($row =~ /^([A-Za-z0-9\-\_]*)/); + if (is_enabled $AIX) { + $user = $1; + $script = `lsuser $user`; + if ( $script =~ /^(\S+)\sid./){ + $module{'user'} = $user; + $module{'_keys'} = ['user']; + push (@{$modules->{$name}}, \%module); + } + } else { + $user = $1; + $script = `passwd -S $user`; + if ( $script =~ /^(\S+)\sP./){ + $module{'user'} = $user; + $module{'_keys'} = ['user']; + push (@{$modules->{$name}}, \%module); } } + + } } # Show Kernel Information sub get_kernel_info ($$) { - my ($name, $modules) = @_; - my $script = `uname -a | tr -d \";\"`; - my %module; + my ($name, $modules) = @_; + my $script = `uname -a | tr -d \";\"`; + my %module; - $module{'Kernel'} = $script; - $module{'_keys'} = ['Kernel']; - push (@{$modules->{$name}}, \%module); + $module{'Kernel'} = $script; + $module{'_keys'} = ['Kernel']; + push (@{$modules->{$name}}, \%module); } @@ -171,11 +261,13 @@ sub get_software_module_data ($$) { # Guess the current distribution my $distrib_id = ""; - if ( -e "/etc/SuSE-release"){ + if (is_enabled $AIX) { + $distrib_id = "AIX"; + }elsif ( -e "/etc/SuSE-release"){ $distrib_id = "SUSE"; - } elsif ( -e "/etc/redhat-release"){ + }elsif ( -e "/etc/redhat-release"){ $distrib_id = "REDHAT"; - } else { + }else { $distrib_id = "DEBIAN"; } @@ -183,7 +275,9 @@ sub get_software_module_data ($$) { my @soft; if ($distrib_id eq 'DEBIAN') { @soft = `dpkg -l | grep ii`; - } else { + }elsif ($distrib_id eq 'AIX') { + @soft = `lslpp -Lcq | awk -F: '{print "ii "\$1" "\$3" "\$8}'`; + }else { # Sometimes rpm return data splitted in two lines, and with dupes. Thats bad for our inventory system @soft = `rpm -q -a --qf "ii %{NAME} %{VERSION} %{SUMMARY}\n" | grep "^ii" | sort -u`; } @@ -197,7 +291,7 @@ sub get_software_module_data ($$) { $module{'program'} = $1; $module{'version'} = $2; $module{'description'} = $3; - # Replace semicolon by comma to avoid parse errors + # Replace semicolon by comma to avoid parse errors $module{'program'} =~ s/;/,/g; $module{'version'} =~ s/;/,/g; $module{'description'} =~ s/;/,/g; @@ -211,67 +305,95 @@ sub get_software_module_data ($$) { #Get the list of interfaces with the ip assigned sub get_ips ($$) { my ($name, $modules) = @_; + my @interfaces; + my $ifconfig; + if (is_enabled $AIX) { + $ifconfig = `ifconfig -a`; + } else { + $ifconfig = `ifconfig`; + } - my $ifconfig = `ifconfig`; - - my @ifconfig_array = split("\n", $ifconfig); - - for(my $i = 0; $i<$#ifconfig_array; $i++) { - - #Check for an interface - if ($ifconfig_array[$i] =~ /Link/) { - my %info; - - my @line_split = split(" ", $ifconfig_array[$i]); - - #Get interface name - $info{'interface'} = $line_split[0]; - #Get IP address - my $line = $ifconfig_array[$i+1]; - - $line =~ s/\s+//g; + my @ifconfig_array = split("\n", $ifconfig); - @line_split = split(":", $line); - - if($line_split[1] =~ /(\d+\.\d+\.\d+\.\d+).+/) { - $info{'ip'} = $1; - } - - $info{'_keys'} = ['interface', 'ip']; - push (@{$modules->{$name}}, \%info); - - } + foreach (@ifconfig_array){ + if ($_=~/(.*)flags/){ + my $match; + ($match)=$_=~/^(.*?)\: flags/; + $match=~s/://; + push @interfaces,$match; + } + } + foreach (@interfaces) { + my $ifconfig_item=`ifconfig $_`; + my $interface=$_; + my @ip_array = split("\n", $ifconfig_item); + foreach (@ip_array) { + if ($_=~/(?<=inet )(.*)(?= netmask)/){ + my $ip; + ($ip)=$_=~/inet (.*) netmask/; + my %info; + $info{'interface'} = $interface; + $info{'ip'} = $ip; + $info{'_keys'} = ['interface','ip']; + push (@{$modules->{$name}}, \%info); + } + } } } #Get route table sub get_route_table ($$) { - my ($name, $modules) = @_; - - my $route_table = `route`; - - my @table_split = split("\n", $route_table); - - for (my $i=2; $i<=$#table_split; $i++) { - - my @split = split(" ", $table_split[$i]); - - my %info; - - $info{'destination'} = $split[0]; - $info{'gateway'} = $split[1]; - $info{'mask'} = $split[2]; - $info{'flags'} = $split[3]; - $info{'metric'} = $split[4]; - $info{'ref'} = $split[5]; - $info{'use'} = $split[6]; - $info{'interface'} = $split[7]; - - $info{'_keys'} = ['destination', 'gateway', 'mask', 'flags', 'metric', 'use', 'interface']; - - push (@{$modules->{$name}}, \%info); - } + my ($name, $modules) = @_; + my $route_table; + my @table_split; + if (is_enabled $AIX) { + $route_table = `netstat -rn`; + @table_split = split("\n", $route_table); + my $length=scalar @table_split; + for (my $i=4; $i<=$length-4; $i++) { + + my @split = split(" ", $table_split[$i]); + + my %info; + + $info{'destination'} = $split[0]; + $info{'gateway'} = $split[1]; + $info{'mask'} = $split[2]; + $info{'flags'} = $split[3]; + $info{'metric'} = $split[4]; + $info{'ref'} = $split[5]; + $info{'use'} = $split[6]; + $info{'interface'} = $split[7]; + + $info{'_keys'} = ['destination', 'gateway', 'mask', 'flags', 'metric', 'use', 'interface']; + + push (@{$modules->{$name}}, \%info); + } + } else { + $route_table = `route`; + my @table_split = split("\n", $route_table); + + for (my $i=2; $i<=$#table_split; $i++) { + + my @split = split(" ", $table_split[$i]); + + my %info; + + $info{'destination'} = $split[0]; + $info{'gateway'} = $split[1]; + $info{'mask'} = $split[2]; + $info{'flags'} = $split[3]; + $info{'metric'} = $split[4]; + $info{'ref'} = $split[5]; + $info{'use'} = $split[6]; + $info{'interface'} = $split[7]; + + $info{'_keys'} = ['destination', 'gateway', 'mask', 'flags', 'metric', 'use', 'interface']; + + push (@{$modules->{$name}}, \%info); + } + } } # Print module data sub print_module ($$) { @@ -309,14 +431,18 @@ my $enable_all = 0; $interval = $ARGV[0]; if ($#ARGV == 0){ - $enable_all = 1; + $enable_all = 1; +} +if ($interval!=/[:alpha:]/){ + splice @ARGV,0,1; } -foreach my $module (@ARGV) { +foreach my $module (@ARGV) { if ($module eq "all"){ - $enable_all = 1; - } - $enabled{$module} = 1; + $enable_all = 1; + }else { + $enabled{$module} = 1; + } } # Check execution interval @@ -333,76 +459,107 @@ close (FILE); # Retrieve hardware information $Mode = 'LSHW'; $Separator = '\s+\*\-'; -my @hwinfo = `lshw 2>/dev/null`; -if ($? != 0) { - $Mode = 'HWINFO'; - $Separator = 'Hardware Class:'; - @hwinfo = `hwinfo --cpu --memory --gfxcard --netcard --cdrom --disk 2>/dev/null`; +my @hwinfo; +if (is_enabled $AIX) { + $Separator = '^\s*$'; + @hwinfo=`prtconf 2>/dev/null`; +} else { + @hwinfo = `lshw 2>/dev/null`; + if ($? != 0) { + $Mode = 'HWINFO'; + $Separator = 'Hardware Class:'; + @hwinfo = `hwinfo --cpu --memory --gfxcard --netcard --cdrom --disk 2>/dev/null`; + } } -# Parse hardware information my %modules; -while (my $line = shift (@hwinfo)) { + + if (is_enabled $AIX) { + #CPU + # VIDEO + ### Not avilable in AIX ### + # NIC + ### Not relevant in AIX ### + if ((test_contain('ent',\@hwinfo)) && ($enable_all == 1 || $enabled{'nic'} == 1)) { + get_module_data_aix ('NIC',\@hwinfo,'^ent',\%modules); + } + if ((test_contain('hdisk',\@hwinfo)) && ($enable_all == 1 || $enabled{'hd'} == 1)) { + get_module_data_aix ('HD',\@hwinfo,'^hdisk',\%modules); + } + + foreach my $line (@hwinfo) { + chomp ($line); + #CPU + if (($line =~ /^Memory Size:/) && ($enable_all == 1 || $enabled{'ram'} == 1)) { + get_module_data_aix_ram_cpu ('RAM', \@hwinfo, ['Memory Size','Good Memory Size'], \%modules); + } + + if (($line =~ /^System Model/) && ($enable_all == 1 || $enabled{'cpu'} == 1)) { + get_module_data_aix_ram_cpu ('CPU', \@hwinfo, ['System Model', 'Processor Implementation Mode', 'Number Of Processors'], \%modules); + } + } +} else { + # Parse hardware information + while (my $line= shift (@hwinfo)) { chomp ($line); + # CPU + if (($line =~ /\*\-cpu/ || $line =~ /Hardware Class: cpu/) && ($enable_all == 1 || $enabled{'cpu'} == 1)) { + if ($Mode eq 'LSHW') { + get_module_data ('CPU', \@hwinfo, ['product', 'vendor', 'capacity'], \%modules); + } else { + get_module_data ('CPU', \@hwinfo, ['Model', 'Vendor', 'Clock'], \%modules); + } + } - # CPU - if (($line =~ /\*\-cpu/ || $line =~ /Hardware Class: cpu/) && ($enable_all == 1 || $enabled{'cpu'} == 1)) { - if ($Mode eq 'LSHW') { - get_module_data ('CPU', \@hwinfo, ['product', 'vendor', 'capacity'], \%modules); - } else { - get_module_data ('CPU', \@hwinfo, ['Model', 'Vendor', 'Clock'], \%modules); - } - } + # RAM + if (($line =~ /\*\-bank/ || $line =~ /\*\-memory/ || $line =~ /Hardware Class: memory/) && ($enable_all == 1 || $enabled{'ram'} == 1)) { + if ($Mode eq 'LSHW') { + get_module_data ('RAM', \@hwinfo, ['description', 'size'], \%modules); + } else { + get_module_data ('RAM', \@hwinfo, ['Model', 'Memory Size'], \%modules); + } + } - # RAM - if (($line =~ /\*\-bank/ || $line =~ /Hardware Class: memory/) && ($enable_all == 1 || $enabled{'ram'} == 1)) { - if ($Mode eq 'LSHW') { - get_module_data ('RAM', \@hwinfo, ['description', 'size'], \%modules); - } else { - get_module_data ('RAM', \@hwinfo, ['Model', 'Memory Size'], \%modules); - } - } + # VIDEO + if (($line =~ /\*\-display/ || $line =~ /Hardware Class: graphics card/) && ($enable_all == 1 || $enabled{'video'} == 1)) { + if ($Mode eq 'LSHW') { + get_module_data ('VIDEO', \@hwinfo, ['product', 'description', 'vendor'], \%modules); + } else { + # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor + get_module_data ('VIDEO', \@hwinfo, ['Model', ' Device', ' Vendor'], \%modules); + } + } - # VIDEO - if (($line =~ /\*\-display/ || $line =~ /Hardware Class: graphics card/) && ($enable_all == 1 || $enabled{'video'} == 1)) { - if ($Mode eq 'LSHW') { - get_module_data ('VIDEO', \@hwinfo, ['product', 'description', 'vendor'], \%modules); - } else { - # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor - get_module_data ('VIDEO', \@hwinfo, ['Model', ' Device', ' Vendor'], \%modules); - } - } + # NIC + if (($line =~ /\*\-network/ || $line =~ /Hardware Class: network/) && ($enable_all == 1 || $enabled{'nic'} == 1)) { + if ($Mode eq 'LSHW') { + get_module_data ('NIC', \@hwinfo, ['product', 'description', 'vendor', 'serial'], \%modules); + } else { + # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor + get_module_data ('NIC', \@hwinfo, ['Model', ' Device', ' Vendor', 'HW Address'], \%modules); + } + } - # NIC - if (($line =~ /\*\-network/ || $line =~ /Hardware Class: network/) && ($enable_all == 1 || $enabled{'nic'} == 1)) { - if ($Mode eq 'LSHW') { - get_module_data ('NIC', \@hwinfo, ['product', 'description', 'vendor', 'serial'], \%modules); - } else { - # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor - get_module_data ('NIC', \@hwinfo, ['Model', ' Device', ' Vendor', 'HW Address'], \%modules); - } - } - - # CDROM - if (($line =~ /\*\-cdrom/ || $line =~ /Hardware Class: cdrom/) && ($enable_all == 1 || $enabled{'cdrom'} == 1)) { - if ($Mode eq 'LSHW') { - get_module_data ('CDROM', \@hwinfo, ['product', 'description', 'vendor'], \%modules); - } else { - # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor - get_module_data ('CDROM', \@hwinfo, ['Model', ' Device', ' Vendor'], \%modules); - } - } + # CDROM + if (($line =~ /\*\-cdrom/ || $line =~ /Hardware Class: cdrom/) && ($enable_all == 1 || $enabled{'cdrom'} == 1)) { + if ($Mode eq 'LSHW') { + get_module_data ('CDROM', \@hwinfo, ['product', 'description', 'vendor'], \%modules); + } else { + # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor + get_module_data ('CDROM', \@hwinfo, ['Model', ' Device', ' Vendor'], \%modules); + } + } - # HD - if (($line =~ /\*\-disk/ || $line =~ /Hardware Class: disk/) && ($enable_all == 1 || $enabled{'hd'} == 1)) { - if ($Mode eq 'LSHW') { - get_module_data ('HD', \@hwinfo, ['product', 'description', 'size'], \%modules); - } else { - get_module_data ('HD', \@hwinfo, ['Model', 'Serial ID', 'Size'], \%modules); - } - } + # HD + if (($line =~ /\*\-disk/ || $line =~ /Hardware Class: disk/) && ($enable_all == 1 || $enabled{'hd'} == 1)) { + if ($Mode eq 'LSHW') { + get_module_data ('HD', \@hwinfo, ['product', 'description', 'size'], \%modules); + } else { + get_module_data ('HD', \@hwinfo, ['Model', 'Serial ID', 'Size'], \%modules); + } + } + } } - # Software if ($enable_all == 1 || $enabled{'software'} == 1) { get_software_module_data ('Software', \%modules); @@ -410,12 +567,12 @@ if ($enable_all == 1 || $enabled{'software'} == 1) { #init_services if ($enable_all == 1 || $enabled{'init_services'} == 1) { - get_servicies_init_machine ('Init services', \%modules); + get_servicies_init_machine ('Init_services', \%modules); } #filesystem if ($enable_all == 1 || $enabled{'filesystem'} == 1) { - get_file_system('File system', \%modules); + get_file_system('Filesystem', \%modules); } #processes @@ -442,7 +599,6 @@ if ($enable_all == 1 || $enabled{'route'} == 1) { if ($enable_all == 1 || $enabled{'kernel'} == 1){ get_kernel_info ('Kernel', \%modules); } - # Print module data print "\n"; while (my ($name, $module) = each (%modules)) { diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index 54ed84c6a3..c2565dea74 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{190425} +{190513} ViewReadme {Yes} diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 36dc750ab8..f67e2bbfb3 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -30,7 +30,7 @@ using namespace Pandora; using namespace Pandora_Strutils; #define PATH_SIZE _MAX_PATH+1 -#define PANDORA_VERSION ("7.0NG.734(Build 190425)") +#define PANDORA_VERSION ("7.0NG.734(Build 190513)") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index 9d8ab88b98..02092b1b5a 100644 --- a/pandora_agents/win32/versioninfo.rc +++ b/pandora_agents/win32/versioninfo.rc @@ -11,7 +11,7 @@ BEGIN VALUE "LegalCopyright", "Artica ST" VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "ProductName", "Pandora FMS Windows Agent" - VALUE "ProductVersion", "(7.0NG.734(Build 190425))" + VALUE "ProductVersion", "(7.0NG.734(Build 190513))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index 9d36c56df1..849366e1a4 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.734-190425 +Version: 7.0NG.734-190513 Architecture: all Priority: optional Section: admin diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh index a645a2ef31..bb58135ccf 100644 --- a/pandora_console/DEBIAN/make_deb_package.sh +++ b/pandora_console/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.734-190425" +pandora_version="7.0NG.734-190513" package_pear=0 package_pandora=1 diff --git a/pandora_console/composer.json b/pandora_console/composer.json index acc6a3e352..208e2d3d14 100644 --- a/pandora_console/composer.json +++ b/pandora_console/composer.json @@ -10,5 +10,16 @@ "require": { "mpdf/mpdf": "^7.1", "swiftmailer/swiftmailer": "^6.0" + }, + "autoload": { + "psr-4": { + "Models\\": "include/rest-api/models", + "Enterprise\\Models\\": "enterprise/include/rest-api/models" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } } } diff --git a/pandora_console/extras/mr/28.sql b/pandora_console/extras/mr/28.sql index 8b87a52375..7789ad60ae 100644 --- a/pandora_console/extras/mr/28.sql +++ b/pandora_console/extras/mr/28.sql @@ -2,4 +2,8 @@ START TRANSACTION; ALTER TABLE `talert_commands` ADD COLUMN `fields_hidden` text; +ALTER TABLE `talert_templates` MODIFY COLUMN `type` ENUM('regex','max_min','max','min','equal','not_equal','warning','critical','onchange','unknown','always','not_normal'); + +DELETE FROM `tevent_response` WHERE `name` LIKE 'Create Integria IMS incident from event'; + COMMIT; diff --git a/pandora_console/extras/pandora_diag.php b/pandora_console/extras/pandora_diag.php index 10e9fbfd42..34cfac8ea4 100644 --- a/pandora_console/extras/pandora_diag.php +++ b/pandora_console/extras/pandora_diag.php @@ -122,7 +122,7 @@ function execution_time() if ($times[0]['datos'] > ($times[1]['datos'] * 1.2)) { return "Warning Status   The execution time could be degrading. For a more extensive information of this data consult the Execution Time graph"; } else { - return "Normal Status   The execution time is correct. For a more extensive information of this data consult the Execution Time graph"; + return "Normal Status   The execution time is correct. For more information about this data, check the Execution Time graph"; } } @@ -173,9 +173,9 @@ function license_capacity() $status_license_capacity = ''; $current_count = db_get_value_sql('SELECT count(*) FROM tagente'); if ($current_count > ($license_limit * 90 / 100)) { - $status_license_capacity = "Warning Status   The license capacity is more than 90 percent"; + $status_license_capacity = "Warning Status   License capacity exceeds 90 percent"; } else { - $status_license_capacity = "Normal Status   The license capacity is less than 90 percent"; + $status_license_capacity = "Normal Status   License capacity is less than 90 percent"; } return $status_license_capacity; @@ -202,9 +202,9 @@ function interval_average_of_network_modules() $average_time = ((int) $total_module_interval_time / $total_network_modules); if ($average_time < 180) { - $status_average_modules = "Warning Status   The system has a lot of load (average time $average_time) and a very fine configuration is required"; + $status_average_modules = "Warning Status   The system is overloaded (average time $average_time) and a very fine configuration is required"; } else { - $status_average_modules = "Normal Status   The system has an acceptable charge (average time $average_time) "; + $status_average_modules = "Normal Status   The system is not overloaded (average time $average_time) "; } if ($average_time == 0) { @@ -221,9 +221,9 @@ $attachment_total_files = count(glob($config['homedir'].'/attachment/{*.*}', GLO function files_attachment_folder($total_files) { if ($total_files <= 700) { - $status_total_files = "Normal Status   The attachment folder has less than 700 files."; + $status_total_files = "Normal Status   The attached folder contains less than 700 files."; } else { - $status_total_files = "Warning Status   The attachment folder has more than 700 files."; + $status_total_files = "Warning Status   The attached folder contains more than 700 files."; } return $status_total_files; @@ -236,9 +236,9 @@ $tagente_datos_size = db_get_value_sql('SELECT COUNT(*) FROM tagente_datos'); function status_tagente_datos($tagente_datos_size) { if ($tagente_datos_size <= 3000000) { - $tagente_datos_size = "Normal Status   The tagente_datos table has an acceptable amount of data."; + $tagente_datos_size = "Normal Status   The tagente_datos table contains an acceptable amount of data."; } else { - $tagente_datos_size = "Warning Status   The tagente_datos table has too much data. A historical database is recommended."; + $tagente_datos_size = "Warning Status   The tagente_datos table contains too much data. A historical database is recommended."; } return $tagente_datos_size; @@ -302,9 +302,9 @@ function status_fragmentation_tables($tables_fragmentation_max_rec_value, $table { $status_tables_frag = ''; if ($tables_fragmentation > $tables_fragmentation_max_rec_value) { - $status_tables_frag = "Warning Status   The fragmentation tables is higher than recommended. You should defragment them."; + $status_tables_frag = "Warning Status   Table fragmentation is higher than recommended. They should be defragmented."; } else { - $status_tables_frag = "Normal Status   The fragmentation tables is correct."; + $status_tables_frag = "Normal Status   Table fragmentation is correct."; } return $status_tables_frag; @@ -320,9 +320,9 @@ if ($console_mode == 1) { echo "\nPandora FMS PHP diagnostic tool v3.2 (c) Artica ST 2009-2010 \n"; if ($argc == 1 || in_array($argv[1], ['--help', '-help', '-h', '-?'])) { - echo "\nThis command line script gives information about Pandora FMS database. -This program only can be executed from console, and need a parameter, the -full path to Pandora FMS 'config.php' file. + echo "\nThis command line script contains information about Pandora FMS database. + This program can only be executed from the console, and it needs a parameter, the + full path to Pandora FMS 'config.php' file. Usage: php pandora_diag.php path_to_pandora_console @@ -705,7 +705,7 @@ render_info_data( render_row($tables_fragmentation_max_rec_value.'%', 'Tables fragmentation (maximum recommended value)'); render_row(number_format($tables_fragmentation, 2).'%', 'Tables fragmentation (current value)'); - render_row(status_fragmentation_tables($tables_fragmentation_max_rec_value, $tables_fragmentation), 'Status fragmentation tables'); + render_row(status_fragmentation_tables($tables_fragmentation_max_rec_value, $tables_fragmentation), 'Table fragmentation status'); echo "".__(' Pandora FMS logs dates').''; @@ -734,14 +734,14 @@ render_info_data( echo "".__(' Status of the attachment folder').''; - render_row($attachment_total_files, 'Total files in the attachment folder'); + render_row($attachment_total_files, 'Total files in the attached folder'); render_row(files_attachment_folder($attachment_total_files), 'Status of the attachment folder'); echo "".__(' Information from the tagente_datos table').''; - render_row($tagente_datos_size, 'Total data in the tagente_datos table'); - render_row(status_tagente_datos($tagente_datos_size), 'Status of the tagente_datos table'); - render_row(execution_time(), 'Degradation of the execution time when executing a count'); + render_row($tagente_datos_size, 'Total data in tagente_datos table'); + render_row(status_tagente_datos($tagente_datos_size), 'Tangente_datos table status'); + render_row(execution_time(), 'Execution time degradation when executing a count'); echo "".__(' Pandora FMS server threads').''; @@ -784,6 +784,6 @@ render_info_data( echo "
"; echo ''.__( - '(*) Please check your Pandora Server setup and be sure that database maintenance daemon is running. It\' very important to -keep up-to-date database to get the best performance and results in Pandora' + '(*) Please check your Pandora Server setup and make sure that the database maintenance daemon is running. It\' is very important to + keep the database up-to-date to get the best performance and results in Pandora' ).'


'; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index c8324692e6..8c76ec87d1 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1217,13 +1217,13 @@ ALTER TABLE titem MODIFY `source_data` int(10) unsigned; INSERT INTO `tconfig` (`token`, `value`) VALUES ('big_operation_step_datos_purge', '100'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('small_operation_step_datos_purge', '1000'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('days_autodisable_deletion', '30'); -INSERT INTO `tconfig` (`token`, `value`) VALUES ('MR', 27); +INSERT INTO `tconfig` (`token`, `value`) VALUES ('MR', 28); INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_docs_logo', 'default_docs.png'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_support_logo', 'default_support.png'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_logo_white_bg_preview', 'pandora_logo_head_white_bg.png'); UPDATE tconfig SET value = 'https://licensing.artica.es/pandoraupdate7/server.php' WHERE token='url_update_manager'; DELETE FROM `tconfig` WHERE `token` = 'current_package_enterprise'; -INSERT INTO `tconfig` (`token`, `value`) VALUES ('current_package_enterprise', '734'); +INSERT INTO `tconfig` (`token`, `value`) VALUES ('current_package_enterprise', '735'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('status_monitor_fields', 'policy,agent,data_type,module_name,server_type,interval,status,graph,warn,data,timestamp'); -- --------------------------------------------------------------------- @@ -2104,3 +2104,9 @@ ALTER TABLE `tnetflow_filter` DROP COLUMN `output`; -- Update table `tuser_task` -- ---------------------------------------------------------------------- UPDATE tuser_task set parameters = 'a:5:{i:0;a:6:{s:11:\"description\";s:28:\"Report pending to be created\";s:5:\"table\";s:7:\"treport\";s:8:\"field_id\";s:9:\"id_report\";s:10:\"field_name\";s:4:\"name\";s:4:\"type\";s:3:\"int\";s:9:\"acl_group\";s:8:\"id_group\";}i:1;a:2:{s:11:\"description\";s:46:\"Send to email addresses (separated by a comma)\";s:4:\"type\";s:4:\"text\";}i:2;a:2:{s:11:\"description\";s:7:\"Subject\";s:8:\"optional\";i:1;}i:3;a:3:{s:11:\"description\";s:7:\"Message\";s:4:\"type\";s:4:\"text\";s:8:\"optional\";i:1;}i:4;a:2:{s:11:\"description\";s:11:\"Report Type\";s:4:\"type\";s:11:\"report_type\";}}' where function_name = "cron_task_generate_report"; + +-- ---------------------------------------------------------------------- +-- Alter table `talert_templates` +-- ---------------------------------------------------------------------- + + ALTER TABLE `talert_templates` MODIFY COLUMN `type` ENUM('regex','max_min','max','min','equal','not_equal','warning','critical','onchange','unknown','always','not_normal'); diff --git a/pandora_console/godmode/agentes/agent_manager.php b/pandora_console/godmode/agentes/agent_manager.php index a7fc1f156a..cee4cb2684 100644 --- a/pandora_console/godmode/agentes/agent_manager.php +++ b/pandora_console/godmode/agentes/agent_manager.php @@ -167,27 +167,18 @@ if ($disk_conf_delete) { echo '
'; -$table = new stdClass(); -$table->width = '100%'; -$table->class = 'databox filters'; - -$table->head = []; -$table->style = []; -$table->style[0] = 'font-weight: bold; width: 150px;'; -$table->data = []; - -$table->align[2] = 'center'; - if (!$new_agent && $alias != '') { - $table->data[0][0] = __('Agent name').ui_print_help_tip(__("The agent's name must be the same as the one defined at the console"), true); - $table->data[0][1] = html_print_input_text('agente', $nombre_agente, '', 50, 100, true); + $table_agent_name = '

'.__('Agent name').': '.ui_print_help_tip(__("The agent's name must be the same as the one defined at the console"), true).'

'; + $table_agent_name .= '
'; + $table_agent_name .= '
'.html_print_input_text('agente', $nombre_agente, '', 50, 100, true).'
'; + $table_agent_name .= '
'; - $table->data[0][2] = __('QR Code Agent view'); + $table_qr_code = '

'.__('QR Code Agent view').':

'; if ($id_agente) { - $table->data[0][1] .= ' '.__('ID')."  $id_agente  "; - $table->data[0][1] .= '  '; - $table->data[0][1] .= html_print_image( + $table_agent_name .= ''.__('ID').' '.$id_agente.''; + $table_agent_name .= ''; + $table_agent_name .= html_print_image( 'images/zoom.png', true, [ @@ -195,20 +186,23 @@ if (!$new_agent && $alias != '') { 'title' => __('Agent detail'), ] ); - $table->data[0][1] .= ''; + $table_agent_name .= ''; } -} -// Remote configuration available -if (!$new_agent) { + $agent_options_update = 'agent_options_update'; + + // Delete link from here. + $table_agent_name .= "".html_print_image('images/cross.png', true, ['title' => __('Delete agent')]).''; + + // Remote configuration available. if (isset($filename)) { if (file_exists($filename['md5'])) { $agent_name = agents_get_name($id_agente); $agent_name = io_safe_output($agent_name); $agent_md5 = md5($agent_name, false); - $table->data[0][1] .= '  '.''; - $table->data[0][1] .= html_print_image( + $table_agent_name .= ''; + $table_agent_name .= html_print_image( 'images/application_edit.png', true, [ @@ -216,35 +210,44 @@ if (!$new_agent) { 'title' => __('This agent can be remotely configured'), ] ); - $table->data[0][1] .= ''.ui_print_help_tip( + $table_agent_name .= ''.ui_print_help_tip( __('You can remotely edit this agent configuration'), true ); } } + + $table_agent_name .= '
'; } -// Delete link from here -if (!$new_agent) { - $table->data[0][1] .= "  ".html_print_image('images/cross.png', true, ['title' => __('Delete agent')]).''; -} - -$table->data[1][0] = __('Alias').ui_print_help_tip(__('Characters /,\,|,%,#,&,$ will be ignored'), true).''; -$table->data[1][1] = html_print_input_text('alias', $alias, '', 50, 100, true); if ($new_agent) { - $table->data[1][1] .= html_print_checkbox('alias_as_name', 1, $config['alias_as_name'], true).__('Use alias as name'); + $label_select_child_left = 'label_select_child_left'; + $label_select_parent = 'label_select_parent'; } -$table->data[2][0] = __('IP Address'); -$table->data[2][1] = html_print_input_text('direccion', $direccion_agente, '', 16, 100, true).html_print_checkbox('unique_ip', 1, $config['unique_ip'], true).__('Unique IP').ui_print_help_tip(__('Set the primary IP address as the unique IP, preventing the same primary IP address from being used in more than one agent'), true); +$table_alias = '

'.__('Alias').': '.ui_print_help_tip(__('Characters /,\,|,%,#,&,$ will be ignored'), true).'

'; +$table_alias .= '
'; +$table_alias .= '
'.html_print_input_text('alias', $alias, '', 50, 100, true).'
'; +if ($new_agent) { + $table_alias .= '
'.html_print_checkbox_switch('alias_as_name', 1, $config['alias_as_name'], true).__('Use alias as name').'
'; +} + +$table_alias .= '
'; + +$table_ip = '

'.__('IP Address').':

'; +$table_ip .= '
'; +$table_ip .= '
'.html_print_input_text('direccion', $direccion_agente, '', 16, 100, true).'
'; +$table_ip .= '
'.html_print_checkbox_switch('unique_ip', 1, $config['unique_ip'], true).__('Unique IP').ui_print_help_tip(__('Set the primary IP address as the unique IP, preventing the same primary IP address from being used in more than one agent'), true).'
'; +$table_ip .= '
'; if ($id_agente) { - $table->data[2][1] .= '    '; - $ip_all = agents_get_addresses($id_agente); - $table->data[2][1] .= html_print_select($ip_all, 'address_list', $direccion_agente, '', '', 0, true); - $table->data[2][1] .= ' '.html_print_checkbox('delete_ip', 1, false, true).__('Delete selected'); + $table_ip .= '
'; + $table_ip .= '
'; + $table_ip .= '
'.html_print_select($ip_all, 'address_list', $direccion_agente, '', '', 0, true).'
'; + $table_ip .= '
'.html_print_checkbox_switch('delete_ip', 1, false, true).__('Delete selected').'
'; + $table_ip .= '
'; } ?> @@ -254,13 +257,12 @@ if ($id_agente) { } rowspan[2][2] = 3; +if (!$new_agent && $alias != '') { if ($id_agente) { - $table->data[2][2] = ""; - } else { - $table->data[2][2] = __('Only it is show when
the agent is saved.'); + $table_qr_code .= ""; } + + $table_qr_code .= '
'; } $groups = users_get_groups($config['id_user'], 'AR', false); @@ -277,28 +279,32 @@ if (is_array($modules)) { } } -$table->data[4][0] = __('Primary group'); -// Cannot change primary group if user have not permission for that group +$table_primary_group = '

'.__('Primary group').':

'; +$table_primary_group .= '
'; +// Cannot change primary group if user have not permission for that group. if (isset($groups[$grupo]) || $new_agent) { - $table->data[4][1] = html_print_select_groups(false, 'AR', false, 'grupo', $grupo, '', '', 0, true); + $table_primary_group .= html_print_select_groups(false, 'AR', false, 'grupo', $grupo, '', '', 0, true); } else { - $table->data[4][1] = groups_get_name($grupo); - $table->data[4][1] .= html_print_input_hidden('grupo', $grupo, true); + $table_primary_group .= groups_get_name($grupo); + $table_primary_group .= html_print_input_hidden('grupo', $grupo, true); } -$table->data[4][1] .= ' '; -$table->data[4][1] .= ui_print_group_icon($grupo, true); -$table->data[4][1] .= ''; +$table_primary_group .= '
'; +$table_primary_group .= ui_print_group_icon($grupo, true); +$table_primary_group .= '
'; -$table->data[5][0] = __('Interval'); - -$table->data[5][1] = html_print_extended_select_for_time('intervalo', $intervalo, '', '', '0', 10, true); +$table_interval = '

'.__('Interval').':

'; +$table_interval .= '
'; +$table_interval .= html_print_extended_select_for_time('intervalo', $intervalo, '', '', '0', 10, true); if ($intervalo < SECONDS_5MINUTES) { - $table->data[5][1] .= clippy_context_help('interval_agent_min'); + $table_interval .= clippy_context_help('interval_agent_min'); } -$table->data[6][0] = __('OS'); -$table->data[6][1] = html_print_select_from_sql( +$table_interval .= '
'; + +$table_os = '

'.__('OS').':

'; +$table_os .= '
'; +$table_os .= html_print_select_from_sql( 'SELECT id_os, name FROM tconfig_os', 'id_os', $id_os, @@ -307,18 +313,19 @@ $table->data[6][1] = html_print_select_from_sql( '0', true ); -$table->data[6][1] .= ' '; -$table->data[6][1] .= ui_print_os_icon($id_os, false, true); -$table->data[6][1] .= ''; +$table_os .= '
'; +$table_os .= ui_print_os_icon($id_os, false, true); +$table_os .= '
'; -// Network server +// Network server. $servers = servers_get_names(); if (!array_key_exists($server_name, $servers)) { $server_Name = 0; // Set the agent have not server. } -$table->data[7][0] = __('Server'); +$table_server = '

'.__('Server').':

'; +$table_server .= '
'; if ($new_agent) { // Set first server by default. $servers_get_names = servers_get_names(); @@ -326,7 +333,7 @@ if ($new_agent) { $server_name = reset($array_keys_servers_get_names); } -$table->data[7][1] = html_print_select( +$table_server .= html_print_select( servers_get_names(), 'server_name', $server_name, @@ -334,36 +341,35 @@ $table->data[7][1] = html_print_select( __('None'), 0, true -).' '.ui_print_help_icon('agent_server', true); +).'
'.ui_print_help_icon('agent_server', true).'
'; -// Description -$table->data[8][0] = __('Description'); -$table->data[8][1] = html_print_input_text( +// Description. +$table_description = '

'.__('Description').':

'; +$table_description .= html_print_input_text( 'comentarios', $comentarios, '', 45, 200, true -); +).'
'; -html_print_table($table); -unset($table); -$table = new stdClass(); -$table->width = '100%'; -$table->class = 'databox filters'; +echo '
+
+
'.$table_agent_name.$table_alias.$table_ip.$table_primary_group.'
+
'.$table_interval.$table_os.$table_server.$table_description.'
+
'; +if (!$new_agent && $alias != '') { + echo $table_qr_code; +} -$table->head = []; -$table->style = []; -$table->style[0] = 'font-weight: bold; '; -$table->style[4] = 'font-weight: bold;'; -$table->data = []; +echo '
'; if (enterprise_installed()) { $secondary_groups_selected = enterprise_hook('agents_get_secondary_groups', [$id_agente]); - $table->data['secondary_groups'][0] = __('Secondary groups').ui_print_help_icon('secondary_groups', true); - $table->data['secondary_groups'][1] = html_print_select_groups( + $table_adv_secondary_groups = '

'.__('Secondary groups').': '.ui_print_help_icon('secondary_groups', true).'

'; + $table_adv_secondary_groups_left = html_print_select_groups( false, // Use the current user to select the groups 'AR', @@ -390,7 +396,7 @@ if (enterprise_installed()) { // CSS classnames (default) false, // Not disabled (default) - false, + 'width:50%; min-width:170px; text-align:center', // Inline styles (default) false, // Option style select (default) @@ -404,29 +410,31 @@ if (enterprise_installed()) { // Do not show the primary group in this selection ); - $table->data['secondary_groups'][2] = html_print_input_image( + $table_adv_secondary_groups_arrows = html_print_input_image( 'add_secondary', - 'images/darrowright.png', + 'images/darrowright_green.png', 1, '', true, [ + 'id' => 'right_autorefreshlist', 'title' => __('Add secondary groups'), 'onclick' => 'agent_manager_add_secondary_groups(event, '.$id_agente.');', ] - ).'



'.html_print_input_image( + ).html_print_input_image( 'remove_secondary', - 'images/darrowleft.png', + 'images/darrowleft_green.png', 1, '', true, [ + 'id' => 'left_autorefreshlist', 'title' => __('Remove secondary groups'), 'onclick' => 'agent_manager_remove_secondary_groups(event, '.$id_agente.');', ] ); - $table->data['secondary_groups'][3] = html_print_select( + $table_adv_secondary_groups_right .= html_print_select( $secondary_groups_selected['for_select'], // Values 'secondary_groups_selected', @@ -441,8 +449,16 @@ if (enterprise_installed()) { // Nothing selected true, // Return HTML (not echo) - true + true, // Multiple selection + true, + // Sort + '', + // Class + false, + // Disabled + 'width:50%; min-width:170px; text-align:center' + // Style ); // safe operation mode @@ -457,47 +473,42 @@ if (enterprise_installed()) { $safe_mode_modules[$m['id_module']] = $m['name']; } - $table->data[2][0] = __('Safe operation mode').ui_print_help_tip( + $table_adv_safe = '

'.__('Safe operation mode').': '.ui_print_help_tip( __( 'This mode allow %s to disable all modules of this agent while the selected module is on CRITICAL status', get_product_name() ), true - ); - $table->data[2][1] = html_print_checkbox('safe_mode', 1, $safe_mode, true); - $table->data[2][1] .= '  '.__('Module').' '.html_print_select($safe_mode_modules, 'safe_mode_module', $safe_mode_module, '', '', 0, true); + ).'

'; + $table_adv_safe .= html_print_checkbox_switch('safe_mode', 1, $safe_mode, true); + $table_adv_safe .= __('Module').' '.html_print_select($safe_mode_modules, 'safe_mode_module', $safe_mode_module, '', '', 0, true).'
'; } // Remote configuration - $table->data[5][0] = __('Remote configuration'); + $table_adv_remote = '

'.__('Remote configuration').':

'; - if (!$new_agent) { - $table->data[5][1] = ''.__('Not available').''; - if (isset($filename)) { - if (file_exists($filename['md5'])) { - $table->data[5][1] = date('F d Y H:i:s', fileatime($filename['md5'])); - // Delete remote configuration - $table->data[5][1] .= ''; - $table->data[5][1] .= html_print_image( - 'images/cross.png', - true, - [ - 'title' => __('Delete remote configuration file'), - 'style' => 'vertical-align: middle;', - ] - ).''; - $table->data[5][1] .= ''.ui_print_help_tip( - __('Delete this conf file implies that for restore you must reactive remote config in the local agent.'), - true - ); - } - } + if (!$new_agent && isset($filename) && file_exists($filename['md5'])) { + $table_adv_remote .= date('F d Y H:i:s', fileatime($filename['md5'])); + // Delete remote configuration + $table_adv_remote .= ''; + $table_adv_remote .= html_print_image( + 'images/cross.png', + true, + [ + 'title' => __('Delete remote configuration file'), + 'style' => 'vertical-align: middle;', + ] + ).''; + $table_adv_remote .= ''.ui_print_help_tip( + __('Delete this conf file implies that for restore you must reactive remote config in the local agent.'), + true + ); } else { - $table->data[5][1] = ''.__('Not available').''; + $table_adv_remote .= ''.__('Not available').''; } - + $table_adv_remote .= '
'; $cps_array[-1] = __('Disabled'); if ($cps > 0) { @@ -511,16 +522,16 @@ if (enterprise_installed()) { $cps_array[$cps_inc] = __('Enabled'); } - $table->data[6][0] = __('Cascade protection services'); - $table->data[6][0] .= ui_print_help_tip(__('Disable the alerts and events of the elements that belong to this service'), true); - $table->data[6][1] = html_print_select($cps_array, 'cps', $cps, '', '', 0, true); + $table_adv_cascade = '

'.__('Cascade protection services').': '; + $table_adv_cascade .= ui_print_help_tip(__('Disable the alerts and events of the elements that belong to this service'), true).'

'; + $table_adv_cascade .= html_print_select($cps_array, 'cps', $cps, '', '', 0, true).'
'; } // Custom ID -$table->data[0][0] = __('Custom ID'); -$table->data[0][1] = html_print_input_text('custom_id', $custom_id, '', 16, 255, true); +$table_adv_custom_id = '

'.__('Custom ID').':

'; +$table_adv_custom_id .= html_print_input_text('custom_id', $custom_id, '', 16, 255, true).'
'; -$table->data[1][0] = __('Parent'); +$table_adv_parent = '

'.__('Parent').':

'; $params = []; $params['return'] = true; $params['show_helptip'] = true; @@ -532,75 +543,79 @@ $params['value'] = db_get_value('alias', 'tagente', 'id_agente', $id_parent); $params['selectbox_id'] = 'cascade_protection_module'; $params['javascript_is_function_select'] = true; $params['cascade_protection'] = true; - -$table->data[1][1] = ui_print_agent_autocomplete_input($params); +$table_adv_parent .= '
'; +$table_adv_parent .= ui_print_agent_autocomplete_input($params); if (enterprise_installed()) { - $table->data[1][1] .= html_print_checkbox('cascade_protection', 1, $cascade_protection, true).__('Cascade protection').' '.ui_print_help_icon('cascade_protection', true); + $table_adv_parent .= html_print_checkbox_switch('cascade_protection', 1, $cascade_protection, true).__('Cascade protection').' '.ui_print_help_icon('cascade_protection', true); } -$table->data[1][1] .= '  '.__('Module').' '.html_print_select($modules_values, 'cascade_protection_module', $cascade_protection_module, '', '', 0, true); +$table_adv_parent .= __('Module').' '.html_print_select($modules_values, 'cascade_protection_module', $cascade_protection_module, '', '', 0, true).'
'; + // Learn mode / Normal mode -$table->data[3][0] = __('Module definition').ui_print_help_icon('module_definition', true); -$table->data[3][1] = __('Learning mode').' '.html_print_radio_button_extended( +$table_adv_module_mode = '

'.__('Module definition').': '.ui_print_help_icon('module_definition', true).'

'; +$table_adv_module_mode .= '
'; +$table_adv_module_mode .= html_print_radio_button_extended( 'modo', 1, - '', + __('Learning mode'), $modo, false, 'show_modules_not_learning_mode_context_help();', - 'style="margin-right: 40px;"', + '', true ); -$table->data[3][1] .= __('Normal mode').' '.html_print_radio_button_extended( +$table_adv_module_mode .= html_print_radio_button_extended( 'modo', 0, - '', + __('Normal mode'), $modo, false, 'show_modules_not_learning_mode_context_help();', - 'style="margin-right: 40px;"', + '', true ); -$table->data[3][1] .= __('Autodisable mode').' '.html_print_radio_button_extended( +$table_adv_module_mode .= html_print_radio_button_extended( 'modo', 2, - '', + __('Autodisable mode'), $modo, false, 'show_modules_not_learning_mode_context_help();', - 'style="margin-right: 40px;"', + '', true ); +$table_adv_module_mode .= '
'; // Status (Disabled / Enabled) -$table->data[4][0] = __('Status'); -$table->data[4][1] = __('Disabled').' '.ui_print_help_tip(__('If the remote configuration is enabled, it will also go into standby mode when disabling it.'), true).' '.html_print_radio_button_extended('disabled', 1, '', $disabled, false, '', 'style="margin-right: 40px;"', true); -$table->data[4][1] .= __('Enabled').' '.html_print_radio_button_extended('disabled', 0, '', $disabled, false, '', 'style="margin-right: 40px;"', true); +$table_adv_status = '

'.__('Disabled').': '.ui_print_help_tip(__('If the remote configuration is enabled, it will also go into standby mode when disabling it.'), true).'

'; +$table_adv_status .= html_print_checkbox_switch('disabled', 1, $disabled, true).'
'; + +// Url address. if (enterprise_installed()) { - $table->data[4][2] = __('Url address').ui_print_help_tip(__('URL address must be complete, for example: https://pandorafms.com/'), true); - $table->data[4][3] = html_print_input_text( + $table_adv_url = '

'.__('Url address').': '.ui_print_help_tip(__('URL address must be complete, for example: https://pandorafms.com/'), true).'

'; + $table_adv_url .= html_print_input_text( 'url_description', $url_description, '', 45, 255, true - ); + ).'
'; } else { - $table->data[5][0] = __('Url address'); - $table->data[5][1] = html_print_input_text( + $table_adv_url = '

'.__('Url address').':

'; + $table_adv_url .= html_print_input_text( 'url_description', $url_description, '', 45, 255, true - ); + ).''; } -$table->data[5][2] = __('Quiet'); -$table->data[5][3] .= ui_print_help_tip(__('The agent still runs but the alerts and events will be stop'), true); -$table->data[5][3] = html_print_checkbox('quiet', 1, $quiet, true); +$table_adv_quiet = '

'.__('Quiet').': '; +$table_adv_quiet .= ui_print_help_tip(__('The agent still runs but the alerts and events will be stop'), true).'

'; +$table_adv_quiet .= html_print_checkbox_switch('quiet', 1, $quiet, true).'
'; $listIcons = gis_get_array_list_icons(); @@ -611,7 +626,7 @@ foreach ($listIcons as $index => $value) { $path = 'images/gis_map/icons/'; // TODO set better method the path -$table->data[0][2] = __('Agent icon').ui_print_help_tip(__('Agent icon for GIS Maps.'), true); +$table_adv_agent_icon = '

'.__('Agent icon').': '.ui_print_help_tip(__('Agent icon for GIS Maps.'), true).'

'; if ($icon_path == '') { $display_icons = 'none'; // Hack to show no icon. Use any given image to fix not found image errors @@ -629,7 +644,7 @@ if ($icon_path == '') { $path_warning = $path.$icon_path.'.warning.png'; } -$table->data[0][3] = html_print_select( +$table_adv_agent_icon .= html_print_select( $arraySelectIcon, 'icon_path', $icon_path, @@ -637,63 +652,68 @@ $table->data[0][3] = html_print_select( __('None'), '', true -).' '.html_print_image( +).html_print_image( $path_ok, true, [ 'id' => 'icon_ok', 'style' => 'display:'.$display_icons.';', ] -).' '.html_print_image( +).html_print_image( $path_bad, true, [ 'id' => 'icon_bad', 'style' => 'display:'.$display_icons.';', ] -).' '.html_print_image( +).html_print_image( $path_warning, true, [ 'id' => 'icon_warning', 'style' => 'display:'.$display_icons.';', ] -); +).'
'; if ($config['activate_gis']) { - $table->data[3][2] = __('Ignore new GIS data:'); - $table->data[3][3] = __('Yes').' '.html_print_radio_button_extended( - 'update_gis_data', - 0, - '', - $update_gis_data, - false, - '', - 'style="margin-right: 40px;"', - true - ); - $table->data[3][3] .= __('No').' '.html_print_radio_button_extended( - 'update_gis_data', - 1, - '', - $update_gis_data, - false, - '', - 'style="margin-right: 40px;"', - true - ); + $table_adv_gis = '

'.__('Ignore new GIS data:').'

'; + if ($new_agent) { + $update_gis_data = true; + } + + $table_adv_gis .= html_print_checkbox_switch('update_gis_data', 1, $update_gis_data, true).'No / Yes
'; } -ui_toggle(html_print_table($table, true), __('Advanced options')); -unset($table); + + +$table_adv_options = $table_adv_secondary_groups.'
+
+ '.$table_adv_secondary_groups_left.' +
+
+ '.$table_adv_secondary_groups_arrows.' +
+
+ '.$table_adv_secondary_groups_right.' +
+
+
+
'.$table_adv_parent.$table_adv_custom_id.$table_adv_module_mode.$table_adv_cascade.$table_adv_gis.'
+
'.$table_adv_agent_icon.$table_adv_url.$table_adv_quiet.$table_adv_status.$table_adv_remote.$table_adv_safe.'
+
'; + +echo '
'; + ui_toggle($table_adv_options, __('Advanced options'), '', true, false, 'white_box white_box_opened'); +echo '
'; + $table = new stdClass(); $table->width = '100%'; -$table->class = 'databox filters'; +$table->class = 'custom_fields_table'; $table->head = []; $table->style = []; -$table->style[0] = 'font-weight: bold; width: 100px;'; +$table->style[0] = 'font-weight: bold;'; $table->data = []; $fields = db_get_all_fields_in_table('tagent_custom_fields'); @@ -703,11 +723,15 @@ if ($fields === false) { } foreach ($fields as $field) { - $data[0] = ''.$field['name'].''; + $id_custom_field = $field['id_field']; + + $data[0] = '
'; + $data[0] .= ''.$field['name'].''; $data[0] .= ui_print_help_tip( __('This field allows url insertion using the BBCode\'s url tag').'.
'.__('The format is: [url=\'url to navigate\']\'text to show\'[/url]').'.

'.__('e.g.: [url=google.com]Google web search[/url]'), true ); + $data[0] .= '
'; $combo = []; $combo = $field['combo_values']; $combo = explode(',', $combo); @@ -730,7 +754,7 @@ foreach ($fields as $field) { } if ($field['is_password_type']) { - $data[1] = html_print_input_text_extended( + $data_field[1] = html_print_input_text_extended( 'customvalue_'.$field['id_field'], $custom_value, 'customvalue_'.$field['id_field'], @@ -744,18 +768,18 @@ foreach ($fields as $field) { true ); } else { - $data[1] = html_print_textarea( + $data_field[1] = html_print_textarea( 'customvalue_'.$field['id_field'], 2, 65, $custom_value, - 'style="min-height: 30px; width:96%;"', + 'style="min-height: 30px;"', true ); } if ($field['combo_values'] !== '') { - $data[1] = html_print_select( + $data_field[1] = html_print_select( $combo_values, 'customvalue_'.$field['id_field'], $custom_value, @@ -776,19 +800,25 @@ foreach ($fields as $field) { ); }; + $table->rowid[] = 'name_field-'.$id_custom_field; array_push($table->data, $data); + + $table->rowid[] = 'field-'.$id_custom_field; + array_push($table->data, $data_field); } if (!empty($fields)) { - ui_toggle(html_print_table($table, true), __('Custom fields')); + echo '
'; + ui_toggle(html_print_table($table, true), __('Custom fields'), '', true, false, 'white_box white_box_opened'); + echo '
'; } -echo '
'; +echo '
'; // The context help about the learning mode. if ($modo == 0) { - echo ""; + echo ""; } else { echo "'; if ($id_agente) { - echo '
'; + echo '
'; html_print_submit_button( __('Update'), 'updbutton', @@ -825,6 +855,19 @@ ui_require_jquery_file('bgiframe'); ?> '; - } } diff --git a/pandora_console/godmode/wizards/Wizard.main.php b/pandora_console/godmode/wizards/Wizard.main.php index 9bdee3b001..dab50570f9 100644 --- a/pandora_console/godmode/wizards/Wizard.main.php +++ b/pandora_console/godmode/wizards/Wizard.main.php @@ -661,22 +661,25 @@ class Wizard $output_submit = ''; $output = ''; - if ($print_white_box === true) + if ($print_white_box === true) { $output .= '
'; + } $output .= '
    '; foreach ($inputs as $input) { - if ($input['arguments']['type']!='submit') + if ($input['arguments']['type'] != 'submit') { $output .= $this->printBlock($input, true); - else + } else { $output_submit .= $this->printBlock($input, true); + } } $output .= '
'; - if ($print_white_box === true) + if ($print_white_box === true) { $output .= '
'; + } $output .= '
    '.$output_submit.'
'; $output .= ''; diff --git a/pandora_console/images/icon_error_db.png b/pandora_console/images/icon_error_db.png new file mode 100644 index 0000000000..1aad380c2f Binary files /dev/null and b/pandora_console/images/icon_error_db.png differ diff --git a/pandora_console/images/icon_error_mr.png b/pandora_console/images/icon_error_mr.png new file mode 100644 index 0000000000..d1e33eed42 Binary files /dev/null and b/pandora_console/images/icon_error_mr.png differ diff --git a/pandora_console/images/icon_info_mr.png b/pandora_console/images/icon_info_mr.png new file mode 100644 index 0000000000..4c0abb0585 Binary files /dev/null and b/pandora_console/images/icon_info_mr.png differ diff --git a/pandora_console/images/icon_success_db.png b/pandora_console/images/icon_success_db.png new file mode 100644 index 0000000000..38511ca06e Binary files /dev/null and b/pandora_console/images/icon_success_db.png differ diff --git a/pandora_console/images/icon_success_mr.png b/pandora_console/images/icon_success_mr.png new file mode 100644 index 0000000000..39c72ea9a1 Binary files /dev/null and b/pandora_console/images/icon_success_mr.png differ diff --git a/pandora_console/images/icon_warning_db.png b/pandora_console/images/icon_warning_db.png new file mode 100644 index 0000000000..f89a7f51b0 Binary files /dev/null and b/pandora_console/images/icon_warning_db.png differ diff --git a/pandora_console/images/update_manager_background.jpg b/pandora_console/images/update_manager_background.jpg new file mode 100644 index 0000000000..121e476860 Binary files /dev/null and b/pandora_console/images/update_manager_background.jpg differ diff --git a/pandora_console/images/update_manager_button.png b/pandora_console/images/update_manager_button.png new file mode 100644 index 0000000000..b18b218d78 Binary files /dev/null and b/pandora_console/images/update_manager_button.png differ diff --git a/pandora_console/include/ajax/custom_fields.php b/pandora_console/include/ajax/custom_fields.php index 0cb9626e7f..9baacdcdc2 100644 --- a/pandora_console/include/ajax/custom_fields.php +++ b/pandora_console/include/ajax/custom_fields.php @@ -1,17 +1,33 @@ $value) { - $values_insert[] = '('.$value['id_server'].', '.$value['id_agente'].", '".$value['description']."', ".$value['status'].')'; + $values_insert[] = '('.$value['id_server'].', '.$value['id_agente'].", '".$value['description']."', '".$value['critical_count']."', '".$value['warning_count']."', '".$value['unknown_count']."', '".$value['notinit_count']."', '".$value['normal_count']."', '".$value['total_count']."', ".$value['status'].')'; } $values_insert_implode = implode(',', $values_insert); $query_insert = 'INSERT INTO temp_custom_fields VALUES '.$values_insert_implode; db_process_sql($query_insert); - // search table for alias, custom field data, server_name, direction + // Search table for alias, custom field data, server_name, direction. $search_query = ''; if ($search['value'] != '') { $search_query = ' AND (tma.alias LIKE "%'.$search['value'].'%"'; @@ -95,7 +134,61 @@ if (check_login()) { $search_query .= ' OR temp.name_custom_fields LIKE "%'.$search['value'].'%" ) '; } - // query all fields result + // Search for status module. + $status_agent_search = ''; + if (isset($id_status) === true && is_array($id_status) === true) { + if (in_array(-1, $id_status) === false) { + if (in_array(AGENT_MODULE_STATUS_NOT_NORMAL, $id_status) === false) { + $status_agent_search = ' AND temp.status IN ('.implode(',', $id_status).')'; + } else { + // Not normal statuses. + $status_agent_search = ' AND temp.status IN (1,2,3,4,5)'; + } + } + } + + // Search for status module. + $status_module_search = ''; + if (isset($module_status) === true && is_array($module_status) === true) { + if (in_array(-1, $module_status) === false) { + if (in_array(AGENT_MODULE_STATUS_NOT_NORMAL, $module_status) === false) { + if (count($module_status) > 0) { + $status_module_search = ' AND ( '; + foreach ($module_status as $key => $value) { + $status_module_search .= ($key != 0) ? ' OR (' : ' ('; + switch ($value) { + default: + case AGENT_STATUS_NORMAL: + $status_module_search .= ' temp.normal_count > 0) '; + break; + case AGENT_STATUS_CRITICAL: + $status_module_search .= ' temp.critical_count > 0) '; + break; + + case AGENT_STATUS_WARNING: + $status_module_search .= ' temp.warning_count > 0) '; + break; + + case AGENT_STATUS_UNKNOWN: + $status_module_search .= ' temp.unknown_count > 0) '; + break; + + case AGENT_STATUS_NOT_INIT: + $status_module_search .= ' temp.notinit_count > 0) '; + break; + } + } + + $status_module_search .= ' ) '; + } + } else { + // Not normal. + $status_module_search = ' AND ( temp.critical_count > 0 OR temp.warning_count > 0 OR temp.unknown_count > 0 AND temp.notinit_count > 0 )'; + } + } + } + + // Query all fields result. $query = sprintf( 'SELECT tma.id_agente, @@ -112,10 +205,14 @@ if (check_login()) { AND temp.id_server = tma.id_tmetaconsole_setup WHERE tma.disabled = 0 %s + %s + %s %s LIMIT %d OFFSET %d ', $search_query, + $status_agent_search, + $status_module_search, $order_by, $length, $start @@ -123,23 +220,27 @@ if (check_login()) { $result = db_get_all_rows_sql($query); - // query count + // Query count. $query_count = sprintf( 'SELECT COUNT(tma.id_agente) AS `count` - FROM tmetaconsole_agent tma - INNER JOIN temp_custom_fields temp - ON temp.id_agent = tma.id_tagente - AND temp.id_server = tma.id_tmetaconsole_setup - WHERE tma.disabled = 0 - %s - ', - $search_query + FROM tmetaconsole_agent tma + INNER JOIN temp_custom_fields temp + ON temp.id_agent = tma.id_tagente + AND temp.id_server = tma.id_tmetaconsole_setup + WHERE tma.disabled = 0 + %s + %s + %s + ', + $search_query, + $status_agent_search, + $status_module_search ); $count = db_get_sql($query_count); - // for link nodes. + // For link nodes. $array_nodes = metaconsole_get_connections(); if (isset($array_nodes) && is_array($array_nodes)) { $hash_array_nodes = []; @@ -158,20 +259,20 @@ if (check_login()) { $user_rot13 = str_rot13($config['id_user']); $hashdata = $user.$pwd; $hashdata = md5($hashdata); - $url_hash = '&'.'loginhash=auto&'.'loginhash_data='.$hashdata.'&'.'loginhash_user='.$user_rot13; + $url_hash = '&loginhash=auto&loginhash_data='.$hashdata.'&loginhash_user='.$user_rot13; $hash_array_nodes[$server['id']]['hashurl'] = $url_hash; $hash_array_nodes[$server['id']]['server_url'] = $server['server_url']; } } - // prepare rows for table dinamic + // Prepare rows for table dinamic. $data = []; foreach ($result as $values) { $image_status = agents_get_image_status($values['status']); - // link nodes - $agent_link = ''; + // Link nodes. + $agent_link = ''; $agent_alias = ui_print_truncate_text( $values['alias'], @@ -225,7 +326,7 @@ if (check_login()) { $name_where = " AND tam.nombre LIKE '%".$module_search."%'"; } - // filter by status module + // Filter by status module. $and_module_status = ''; if (is_array($module_status)) { if (!in_array(-1, $module_status)) { @@ -260,7 +361,7 @@ if (check_login()) { $and_module_status .= ' ) '; } } else { - // not normal + // Not normal. $and_module_status = 'AND tae.estado <> 0 AND tae.estado <> 300 '; } } @@ -314,7 +415,12 @@ if (check_login()) { && $value['id_tipo_modulo'] != 23 && $value['id_tipo_modulo'] != 33 ) { - $table_modules->data[$key][1] = remove_right_zeros(number_format($value['datos'], $config['graph_precision'])); + $table_modules->data[$key][1] = remove_right_zeros( + number_format( + $value['datos'], + $config['graph_precision'] + ) + ); } else { $table_modules->data[$key][1] = $value['datos']; } @@ -329,7 +435,10 @@ if (check_login()) { ); $table_modules->data[$key][3] = $value['current_interval']; - $table_modules->data[$key][4] = ui_print_timestamp($value['utimestamp'], true); + $table_modules->data[$key][4] = ui_print_timestamp( + $value['utimestamp'], + true + ); switch ($value['estado']) { case 0: case 300: @@ -398,7 +507,7 @@ if (check_login()) { } } - // status agents from tagente + // Status agents from tagente. $sql_info_agents = 'SELECT * fROM tagente WHERE id_agente ='.$id_agent; $info_agents = db_get_row_sql($sql_info_agents); $status_agent = agents_get_status_from_counts($info_agents); @@ -463,7 +572,13 @@ if (check_login()) { false ); - $table->data[0][3] = html_print_submit_button(__('Load filter'), 'load_filter', false, 'class="sub upd"', true); + $table->data[0][3] = html_print_submit_button( + __('Load filter'), + 'load_filter', + false, + 'class="sub upd"', + true + ); echo "
"; html_print_table($table); @@ -474,7 +589,12 @@ if (check_login()) { } if ($append_tab_filter) { - $filters = json_decode(io_safe_output(get_parameter('filters', '')), true); + $filters = json_decode( + io_safe_output( + get_parameter('filters', '') + ), + true + ); $table = new StdClass; $table->id = 'save_filter_form'; @@ -485,7 +605,14 @@ if (check_login()) { if ($filters['id'] == 'extended_create_filter') { echo "
"; $table->data[0][0] = __('Filter name'); - $table->data[0][1] = html_print_input_text('id_name', '', '', 15, 255, true); + $table->data[0][1] = html_print_input_text( + 'id_name', + '', + '', + 15, + 255, + true + ); $table->data[1][0] = __('Group'); $table->data[1][1] = html_print_select_groups( @@ -510,7 +637,13 @@ if (check_login()) { ); $table->rowspan[0][2] = 2; - $table->data[0][2] = html_print_submit_button(__('Create filter'), 'create_filter', false, 'class="sub upd"', true); + $table->data[0][2] = html_print_submit_button( + __('Create filter'), + 'create_filter', + false, + 'class="sub upd"', + true + ); } else { echo "
"; echo "
"; @@ -552,8 +685,20 @@ if (check_login()) { false ); - $table->data[0][2] = html_print_submit_button(__('Delete filter'), 'delete_filter', false, 'class="sub upd"', true); - $table->data[1][2] = html_print_submit_button(__('Update filter'), 'update_filter', false, 'class="sub upd"', true); + $table->data[0][2] = html_print_submit_button( + __('Delete filter'), + 'delete_filter', + false, + 'class="sub upd"', + true + ); + $table->data[1][2] = html_print_submit_button( + __('Update filter'), + 'update_filter', + false, + 'class="sub upd"', + true + ); } html_print_table($table); @@ -561,17 +706,20 @@ if (check_login()) { } if ($create_filter_cf) { - // initialize result + // Initialize result. $result_array = []; $result_array['error'] = 0; $result_array['msg'] = ''; - // initialize vars - $filters = json_decode(io_safe_output(get_parameter('filters', '')), true); + // Initialize vars. + $filters = json_decode( + io_safe_output(get_parameter('filters', '')), + true + ); $name_filter = get_parameter('name_filter', ''); $group_search = get_parameter('group_search', 0); - // check that the name is not empty + // Check that the name is not empty. if ($name_filter == '') { $result_array['error'] = 1; $result_array['msg'] = ui_print_error_message( @@ -596,7 +744,7 @@ if (check_login()) { return; } - // check custom field is not empty + // Check custom field is not empty. if ($filters['id_custom_fields'] == '') { $result_array['error'] = 1; $result_array['msg'] = ui_print_error_message( @@ -608,13 +756,15 @@ if (check_login()) { return; } - // insert + // Insert. $values = []; $values['name'] = $name_filter; $values['group_search'] = $group_search; $values['id_group'] = $filters['group']; $values['id_custom_field'] = $filters['id_custom_fields']; - $values['id_custom_fields_data'] = json_encode($filters['id_custom_fields_data']); + $values['id_custom_fields_data'] = json_encode( + $filters['id_custom_fields_data'] + ); $values['id_status'] = json_encode($filters['id_status']); $values['module_search'] = $filters['module_search']; $values['module_status'] = json_encode($filters['module_status']); @@ -622,7 +772,7 @@ if (check_login()) { $insert = db_process_sql_insert('tagent_custom_fields_filter', $values); - // check error insert + // Check error insert. if ($insert) { $result_array['error'] = 0; $result_array['msg'] = ui_print_success_message( @@ -644,17 +794,17 @@ if (check_login()) { } if ($update_filter_cf) { - // initialize result + // Initialize result. $result_array = []; $result_array['error'] = 0; $result_array['msg'] = ''; - // initialize vars + // Initialize vars. $filters = json_decode(io_safe_output(get_parameter('filters', '')), true); $id_filter = get_parameter('id_filter', ''); $group_search = get_parameter('group_search', 0); - // check selected filter + // Check selected filter. if ($id_filter == -1) { $result_array['error'] = 1; $result_array['msg'] = ui_print_error_message( @@ -666,11 +816,11 @@ if (check_login()) { return; } - // array condition update + // Array condition update. $condition = []; $condition['id'] = $id_filter; - // check selected custom fields + // Check selected custom fields. if ($filters['id_custom_fields'] == '') { $result_array['error'] = 1; $result_array['msg'] = ui_print_error_message( @@ -682,7 +832,7 @@ if (check_login()) { return; } - // array values update + // Array values update. $values = []; $values['id_group'] = $filters['group']; $values['group_search'] = $group_search; @@ -693,10 +843,10 @@ if (check_login()) { $values['module_status'] = json_encode($filters['module_status']); $values['recursion'] = $filters['recursion']; - // update + // Update. $update = db_process_sql_update('tagent_custom_fields_filter', $values, $condition); - // check error insert + // Check error insert. if ($update) { $result_array['error'] = 0; $result_array['msg'] = ui_print_success_message( @@ -718,16 +868,16 @@ if (check_login()) { } if ($delete_filter_cf) { - // Initialize result + // Initialize result. $result_array = []; $result_array['error'] = 0; $result_array['msg'] = ''; - // Initialize vars + // Initialize vars. $filters = json_decode(io_safe_output(get_parameter('filters', '')), true); $id_filter = get_parameter('id_filter', ''); - // Check selected filter + // Check selected filter. if ($id_filter == -1) { $result_array['error'] = 1; $result_array['msg'] = ui_print_error_message( @@ -739,14 +889,14 @@ if (check_login()) { return; } - // Array condition update + // Array condition update. $condition = []; $condition['id'] = $id_filter; - // Delete + // Delete. $delete = db_process_sql_delete('tagent_custom_fields_filter', $condition); - // Check error insert + // Check error insert. if ($delete) { $result_array['error'] = 0; $result_array['msg'] = ui_print_success_message( diff --git a/pandora_console/include/ajax/events.php b/pandora_console/include/ajax/events.php index 6b7be8eb28..6ba163c7ed 100644 --- a/pandora_console/include/ajax/events.php +++ b/pandora_console/include/ajax/events.php @@ -418,15 +418,15 @@ if ($get_extended_event) { } // Tabs. - $tabs = "
    "; - $tabs .= "
  • ".html_print_image('images/lightning_go.png', true)."".__('General').'
  • '; + $tabs = "
      "; + $tabs .= "
    • ".html_print_image('images/lightning_go.png', true).''.__('General').'
    • '; if (events_has_extended_info($event['id_evento']) === true) { - $tabs .= "
    • ".html_print_image('images/zoom.png', true)."".__('Related').'
    • '; + $tabs .= "
    • ".html_print_image('images/zoom.png', true).''.__('Related').'
    • '; } - $tabs .= "
    • ".html_print_image('images/zoom.png', true)."".__('Details').'
    • '; - $tabs .= "
    • ".html_print_image('images/custom_field_col.png', true)."".__('Agent fields').'
    • '; - $tabs .= "
    • ".html_print_image('images/pencil.png', true)."".__('Comments').'
    • '; + $tabs .= "
    • ".html_print_image('images/zoom.png', true).''.__('Details').'
    • '; + $tabs .= "
    • ".html_print_image('images/custom_field_col.png', true).''.__('Agent fields').'
    • '; + $tabs .= "
    • ".html_print_image('images/pencil.png', true).''.__('Comments').'
    • '; if (!$readonly && ((tags_checks_event_acl( @@ -546,7 +546,7 @@ if ($get_extended_event) { $loading = ''; - $out = '
      '.$tabs.$notifications.$loading.$general.$details.$related.$custom_fields.$comments.$responses.$custom_data.html_print_input_hidden('id_event', $event['id_evento']).'
      '; + $out = '
      '.$tabs.$notifications.$loading.$general.$details.$related.$custom_fields.$comments.$responses.$custom_data.html_print_input_hidden('id_event', $event['id_evento']).'
      '; $js = ''; + continue; + } + + preg_match('/.*.css$/', $file, $match, PREG_OFFSET_CAPTURE); + if (empty($match) === false) { + $url = $baseUrl.$vcClientPath.'/'.$match[0][0]; + echo ''; + } + } + + closedir($dh); + } + } +} diff --git a/pandora_console/include/functions_visual_map_editor.php b/pandora_console/include/functions_visual_map_editor.php index 151014cd01..5cf5121e55 100755 --- a/pandora_console/include/functions_visual_map_editor.php +++ b/pandora_console/include/functions_visual_map_editor.php @@ -688,7 +688,7 @@ function visual_map_editor_print_item_palette($visualConsole_id, $background) 'percentile_item', 'datos', ]; - $form_items['percentile_item_row_6']['html'] = ''.__('Label color').' + $form_items['percentile_item_row_6']['html'] = ''.__('Value color').' '.html_print_input_text_extended( 'percentile_label_color', '#ffffff', @@ -1394,6 +1394,9 @@ function visual_map_editor_print_hack_translate_strings() - + $now) { $urlImage = ui_get_full_url(false); - echo '
      '; + // Graph. + echo '
      '; $height = 400; $width = '90%'; @@ -177,27 +178,14 @@ if ($date > $now) { echo '
      '; - // - // SIDE MENU - // - $side_layer_params = []; - // TOP TEXT - $side_layer_params['top_text'] = "
      ".html_print_image('/images/config.disabled.png', true, ['width' => '16px'], false, false, false, true).' '.__('Graph configuration menu').'
      '; - $side_layer_params['body_text'] = "'; - // outer - // ICONS - $side_layer_params['icon_closed'] = '/images/graphmenu_arrow_hide.png'; - $side_layer_params['icon_open'] = '/images/graphmenu_arrow.png'; - - // SIZE - $side_layer_params['width'] = 500; - - // POSITION - $side_layer_params['position'] = 'left'; - - html_print_side_layer($side_layer_params); + echo $menu_form; + echo '
      +
      + '.html_print_image('images/arrow_down_green.png', true, ['class' => 'module_graph_menu_arrow', 'float' => 'left'], false, false, true).' + '.__('Graph configuration menu').ui_print_help_icon('graphs', true, $config['homeurl'], 'images/help_g.png', true).' + '.html_print_image('images/config.png', true, ['float' => 'right'], false, false, true).' +
      + +
      '; + echo ''; // Hidden div to forced title html_print_div(['id' => 'forced_title_layer', 'class' => 'forced_title_layer', 'hidden' => true]); @@ -341,4 +321,22 @@ ui_include_time_picker(true); $.datepicker.setDefaults($.datepicker.regional[""]); forced_title_callback(); + + // Menu. + $('#module_graph_menu_header').on('click', function(){ + var arrow = $('#module_graph_menu_header .module_graph_menu_arrow'); + var arrow_up = 'arrow_up_green'; + var arrow_down = 'arrow_down_green'; + if( $('.module_graph_menu_content').hasClass('module_graph_menu_content_closed')){ + $('.module_graph_menu_content').show(); + $('.module_graph_menu_content').removeClass('module_graph_menu_content_closed'); + arrow.attr('src',arrow.attr('src').replace(arrow_down, arrow_up)); + } + else{ + $('.module_graph_menu_content').hide(); + $('.module_graph_menu_content').addClass('module_graph_menu_content_closed'); + arrow.attr('src',arrow.attr('src').replace(arrow_up, arrow_down)); + } + }); + diff --git a/pandora_console/operation/agentes/stat_win.php b/pandora_console/operation/agentes/stat_win.php index 78cd56cfcc..ef4a448360 100644 --- a/pandora_console/operation/agentes/stat_win.php +++ b/pandora_console/operation/agentes/stat_win.php @@ -89,7 +89,7 @@ $alias = db_get_value('alias', 'tagente', 'id_agente', $id_agent); }; - + "; @@ -175,8 +175,9 @@ $alias = db_get_value('alias', 'tagente', 'id_agente', $id_agent); $unit = db_get_value('unit', 'tagente_modulo', 'id_agente_modulo', $id); - echo '
      '; + // Graph. + echo '
      '; $width = '90%'; $height = '450'; @@ -228,39 +229,16 @@ $alias = db_get_value('alias', 'tagente', 'id_agente', $id_agent); echo '
      '; - // - // SIDE MENU - // - $params = []; - // TOP TEXT - // Use the no_meta parameter because this image is only in the base console - $params['top_text'] = "
      ".html_print_image('images/wrench_blanco.png', true, ['width' => '16px'], false, false, true).' '.__('Graph configuration menu').ui_print_help_icon('graphs', true, $config['homeurl'], 'images/help_w.png', true).'
      '; - $params['body_text'] = "'; - unset($table); - $table = new stdClass(); - $table->id = 'stat_win_form'; - $table->width = '100%'; - $table->cellspacing = 2; - $table->cellpadding = 2; - $table->class = 'databox'; + // Menu. + $menu_form = "".html_print_input_hidden('id', $id, true).html_print_input_hidden('label', $label, true); - $data = []; - $data[0] = html_print_div( - [ - 'id' => 'field_list', - 'content' => $form_table, - 'style' => 'overflow: auto; height: 220px', - ], - true - ); - $table->data[] = $data; - $table->rowclass[] = ''; + if (!empty($server_id)) { + $menu_form .= html_print_input_hidden('server', $server_id, true); + } - $params['body_text'] .= html_print_table($table, true); - $params['body_text'] .= ''; - $params['body_text'] .= '
      '; - // outer - // ICONS - $params['icon_closed'] = '/images/graphmenu_arrow_hide.png'; - $params['icon_open'] = '/images/graphmenu_arrow.png'; + if (isset($_GET['type'])) { + $type = get_parameter_get('type'); + $menu_form .= html_print_input_hidden('type', $type, true); + } - // SIZE - $params['width'] = 500; - - // POSITION - $params['position'] = 'left'; - - html_print_side_layer($params); + echo $menu_form; + echo '
      +
      + '.html_print_image('images/arrow_down_green.png', true, ['class' => 'module_graph_menu_arrow', 'float' => 'left'], false, false, true).' + '.__('Graph configuration menu').ui_print_help_icon('graphs', true, $config['homeurl'], 'images/help_g.png', true).' + '.html_print_image('images/config.png', true, ['float' => 'right'], false, false, true).' +
      + +
      '; + echo ''; // Hidden div to forced title html_print_div( @@ -491,11 +456,21 @@ ui_include_time_picker(true); $.datepicker.setDefaults($.datepicker.regional[""]); - $(window).ready(function() { - $("#field_list").css('height', ($(window).height() - 160) + 'px'); + // Menu. + $('#module_graph_menu_header').on('click', function(){ + var arrow = $('#module_graph_menu_header .module_graph_menu_arrow'); + var arrow_up = 'arrow_up_green'; + var arrow_down = 'arrow_down_green'; + if( $('.module_graph_menu_content').hasClass('module_graph_menu_content_closed')){ + $('.module_graph_menu_content').show(); + $('.module_graph_menu_content').removeClass('module_graph_menu_content_closed'); + arrow.attr('src',arrow.attr('src').replace(arrow_down, arrow_up)); + } + else{ + $('.module_graph_menu_content').hide(); + $('.module_graph_menu_content').addClass('module_graph_menu_content_closed'); + arrow.attr('src',arrow.attr('src').replace(arrow_up, arrow_down)); + } }); - $(window).resize(function() { - $("#field_list").css('height', ($(document).height() - 160) + 'px'); - }); diff --git a/pandora_console/operation/events/events.build_table.php b/pandora_console/operation/events/events.build_table.php index d4b3ed3a30..3e112f3fb8 100644 --- a/pandora_console/operation/events/events.build_table.php +++ b/pandora_console/operation/events/events.build_table.php @@ -896,7 +896,7 @@ if ($group_rep == 2) { // Checkbox $data[$i] = html_print_checkbox_extended('validate_ids[]', $event['id_evento'], false, false, false, 'class="chk_val"', true); } else if (isset($table->header[$i]) || true) { - $data[$i] = ''; + $data[$i] = html_print_checkbox_extended('validate_ids[]', $event['id_evento'], false, false, false, 'class="chk_val"', true); } } diff --git a/pandora_console/operation/events/events.php b/pandora_console/operation/events/events.php index b259e35e66..09f952108c 100644 --- a/pandora_console/operation/events/events.php +++ b/pandora_console/operation/events/events.php @@ -285,8 +285,38 @@ if (!$meta) { } } +$id_filter = db_get_value( + 'id_filter', + 'tusuario', + 'id_user', + $config['id_user'] +); + +// If user has event filter retrieve filter values. +if (!empty($id_filter)) { + $apply_filter = true; + + $event_filter = events_get_event_filter($id_filter); + + $event_filter['search'] = io_safe_output($event_filter['search']); + $event_filter['id_name'] = io_safe_output($event_filter['id_name']); + $event_filter['tag_with'] = base64_encode( + io_safe_output($event_filter['tag_with']) + ); + $event_filter['tag_without'] = base64_encode( + io_safe_output($event_filter['tag_without']) + ); +} + +$is_filtered = get_parameter('is_filtered', false); $offset = (int) get_parameter('offset', 0); + +if ($event_filter['id_group'] == '') { + $event_filter['id_group'] = 0; +} + $id_group = (int) get_parameter('id_group', 0); + // 0 all // ********************************************************************** // TODO @@ -297,38 +327,59 @@ $id_group = (int) get_parameter('id_group', 0); // ********************************************************************** $recursion = (bool) get_parameter('recursion', true); // Flag show in child groups. -$event_type = get_parameter('event_type', ''); +if (empty($event_filter['event_type'])) { + $event_filter['event_type'] = ''; +} + +$event_type = ($apply_filter === true && $is_filtered === false) ? $event_filter['event_type'] : get_parameter('event_type', ''); + // 0 all. -$severity = (int) get_parameter('severity', -1); +$severity = ($apply_filter === true && $is_filtered === false) ? (int) $event_filter['severity'] : (int) get_parameter('severity', -1); // -1 all. -$status = (int) get_parameter('status', 3); +if ($event_filter['status'] == -1) { + $event_filter['status'] = 3; +} + +$status = ($apply_filter === true && $is_filtered === false) ? (int) $event_filter['status'] : (int) get_parameter('status', 3); // -1 all, 0 only new, 1 only validated, // 2 only in process, 3 only not validated. -$id_agent = (int) get_parameter('id_agent', 0); -$pagination = (int) get_parameter('pagination', $config['block_size']); -$event_view_hr = (int) get_parameter( +$id_agent = ($apply_filter === true && $is_filtered === false) ? (int) $event_filter['id_agent'] : (int) get_parameter('id_agent', 0); +$pagination = ($apply_filter === true && $is_filtered === false) ? (int) $event_filter['pagination'] : (int) get_parameter('pagination', $config['block_size']); + +if (empty($event_filter['event_view_hr'])) { + $event_filter['event_view_hr'] = ($history) ? 0 : $config['event_view_hr']; +} + +$event_view_hr = ($apply_filter === true && $is_filtered === false) ? (int) $event_filter['event_view_hr'] : (int) get_parameter( 'event_view_hr', ($history) ? 0 : $config['event_view_hr'] ); -$id_user_ack = get_parameter('id_user_ack', 0); -$group_rep = (int) get_parameter('group_rep', 1); + + +$id_user_ack = ($apply_filter === true && $is_filtered === false) ? $event_filter['id_user_ack'] : get_parameter('id_user_ack', 0); +$group_rep = ($apply_filter === true && $is_filtered === false) ? (int) $event_filter['group_rep'] : (int) get_parameter('group_rep', 1); $delete = (bool) get_parameter('delete'); $validate = (bool) get_parameter('validate', 0); $section = (string) get_parameter('section', 'list'); -$filter_only_alert = (int) get_parameter('filter_only_alert', -1); +$filter_only_alert = ($apply_filter === true && $is_filtered === false) ? (int) $event_filter['filter_only_alert'] : (int) get_parameter('filter_only_alert', -1); $filter_id = (int) get_parameter('filter_id', 0); -$id_name = (string) get_parameter('id_name', ''); + +if (empty($event_filter['id_name'])) { + $event_filter['id_name'] = ''; +} + +$id_name = ($apply_filter === true && $is_filtered === false) ? (string) $event_filter['id_name'] : (string) get_parameter('id_name', ''); $open_filter = (int) get_parameter('open_filter', 0); -$date_from = (string) get_parameter('date_from', ''); -$date_to = (string) get_parameter('date_to', ''); +$date_from = ($apply_filter === true && $is_filtered === false) ? (string) $event_filter['date_from'] : (string) get_parameter('date_from', ''); +$date_to = ($apply_filter === true && $is_filtered === false) ? (string) $event_filter['date_to'] : (string) get_parameter('date_to', ''); $time_from = (string) get_parameter('time_from', ''); $time_to = (string) get_parameter('time_to', ''); $server_id = (int) get_parameter('server_id', 0); -$text_agent = (string) get_parameter('text_agent'); +$text_agent = ($apply_filter === true && $is_filtered === false) ? (string) $event_filter['text_agent'] : (string) get_parameter('text_agent'); $refr = (int) get_parameter('refresh'); -$id_extra = (string) get_parameter('id_extra'); -$user_comment = (string) get_parameter('user_comment'); -$source = (string) get_parameter('source'); +$id_extra = ($apply_filter === true && $is_filtered === false) ? (string) $event_filter['id_extra'] : (string) get_parameter('id_extra'); +$user_comment = ($apply_filter === true && $is_filtered === false) ? (string) $event_filter['user_comment'] : (string) get_parameter('user_comment'); +$source = ($apply_filter === true && $is_filtered === false) ? (string) $event_filter['source'] : (string) get_parameter('source'); if ($id_agent != 0) { $text_agent = agents_get_alias($id_agent); @@ -343,7 +394,7 @@ if ($id_agent != 0) { } $text_module = (string) get_parameter('module_search', ''); -$id_agent_module = get_parameter( +$id_agent_module = ($apply_filter === true && $is_filtered === false) ? $event_filter['id_agent_module'] : get_parameter( 'module_search_hidden', get_parameter('id_agent_module', 0) ); @@ -363,7 +414,7 @@ if ($id_agent_module != 0) { -$tag_with_json = base64_decode(get_parameter('tag_with', '')); +$tag_with_json = ($apply_filter === true && $is_filtered === false) ? base64_decode($event_filter['tag_with']) : base64_decode(get_parameter('tag_with', '')); $tag_with_json_clean = io_safe_output($tag_with_json); $tag_with_base64 = base64_encode($tag_with_json_clean); $tag_with = json_decode($tag_with_json_clean, true); @@ -373,7 +424,7 @@ if (empty($tag_with)) { $tag_with = array_diff($tag_with, [0 => 0]); -$tag_without_json = base64_decode(get_parameter('tag_without', '')); +$tag_without_json = ($apply_filter === true && $is_filtered === false) ? base64_decode($event_filter['tag_without']) : base64_decode(get_parameter('tag_without', '')); $tag_without_json_clean = io_safe_output($tag_without_json); $tag_without_base64 = base64_encode($tag_without_json_clean); $tag_without = json_decode($tag_without_json_clean, true); @@ -886,11 +937,11 @@ $(document).ready( function() { // Remove delete link (if event is not grouped and there is more than one event) if ($("#group_rep").val() == 1) { if (parseInt($("#count_event_group_"+id).text()) <= 1) { - $("#delete-"+id).replaceWith('' + <?php echo + '" title="' + + '" src="images/cross.disabled.png">'); + $("#delete-"+id).replaceWith(' <?php echo addslashes(__('Is not allowed delete events in process')); ?>'); } } else { // Remove delete link (if event is not grouped) - $("#delete-"+id).replaceWith('' + <?php echo + '" title="' + + '" src="images/cross.disabled.png">'); + $("#delete-"+id).replaceWith('<?php echo addslashes(__('Is not allowed delete events in process')); ?> '); } // Change state image @@ -1091,10 +1142,10 @@ function validate_event_advanced(id, new_status) { $("#in-progress-"+id).remove(); // Format the new disabled delete icon. $("#validate-"+id).parent().append(""); - $("#delete-"+id).attr ("data-title", ); - $("#delete-"+id).attr ("alt", ); + $("#delete-"+id).attr ("data-title", ""); + $("#delete-"+id).attr ("alt"," "); $("#delete-"+id).attr ("data-use_title_for_force_title", 1); - $("#delete-"+id).attr ("class", "forced_title"); + $("#delete-"+id).attr ("class", "forced_title"); // Remove row due to new state if (($("#status").val() == 0) @@ -1142,4 +1193,4 @@ if ($load_event) { } ?> /* ]]> */ - + \ No newline at end of file diff --git a/pandora_console/operation/events/events_list.php b/pandora_console/operation/events/events_list.php index 2146447272..8333ca5b0d 100644 --- a/pandora_console/operation/events/events_list.php +++ b/pandora_console/operation/events/events_list.php @@ -232,68 +232,70 @@ if ($user_filter != 0 && empty($id_name) && !$update_from_filter_table) { ); $user_default_filter = $user_default_filter[0]; - // FORM. - $id_name = $user_default_filter['id_name']; - $id_group = $user_default_filter['id_group']; - if ($user_default_filter['event_type'] != '') { - $event_type = $user_default_filter['event_type']; - } + if (!empty($user_default_filter)) { + // FORM. + $id_name = $user_default_filter['id_name']; + $id_group = $user_default_filter['id_group']; + if ($user_default_filter['event_type'] != '') { + $event_type = $user_default_filter['event_type']; + } - $severity = $user_default_filter['severity']; - $status = $user_default_filter['status']; - $event_view_hr = $user_default_filter['event_view_hr']; - $group_rep = $user_default_filter['group_rep']; - $id_extra = $user_default_filter['id_extra']; - $user_comment = $user_default_filter['user_comment']; - $source = $user_default_filter['source']; + $severity = $user_default_filter['severity']; + $status = $user_default_filter['status']; + $event_view_hr = $user_default_filter['event_view_hr']; + $group_rep = $user_default_filter['group_rep']; + $id_extra = $user_default_filter['id_extra']; + $user_comment = $user_default_filter['user_comment']; + $source = $user_default_filter['source']; - if ($user_default_filter['search'] != '') { - $search = $user_default_filter['search']; - } + if ($user_default_filter['search'] != '') { + $search = $user_default_filter['search']; + } - if ($user_default_filter['id_user_ack'] != 0) { - $id_user_ack = $user_default_filter['id_user_ack']; - } + if ($user_default_filter['id_user_ack'] != 0) { + $id_user_ack = $user_default_filter['id_user_ack']; + } - if ($user_default_filter['id_agent_module'] != 0) { - $id_agent_module = $user_default_filter['id_agent_module']; - } + if ($user_default_filter['id_agent_module'] != 0) { + $id_agent_module = $user_default_filter['id_agent_module']; + } - if ($user_default_filter['id_agent'] != 0) { - $id_agent = $user_default_filter['id_agent']; - $text_agent = agents_get_alias($id_agent); - } + if ($user_default_filter['id_agent'] != 0) { + $id_agent = $user_default_filter['id_agent']; + $text_agent = agents_get_alias($id_agent); + } - if ($user_default_filter['filter_only_alert'] != -1) { - $filter_only_alert = $user_default_filter['filter_only_alert']; - } + if ($user_default_filter['filter_only_alert'] != -1) { + $filter_only_alert = $user_default_filter['filter_only_alert']; + } - if ($user_default_filter['pagination'] != 20) { - $pagination = $user_default_filter['pagination']; - } + if ($user_default_filter['pagination'] != 20) { + $pagination = $user_default_filter['pagination']; + } - if ($user_default_filter['date_from'] != '0000-00-00') { - $date_from = $user_default_filter['date_from']; - } + if ($user_default_filter['date_from'] != '0000-00-00') { + $date_from = $user_default_filter['date_from']; + } - if ($user_default_filter['date_to'] != '0000-00-00') { - $date_to = $user_default_filter['date_to']; - } + if ($user_default_filter['date_to'] != '0000-00-00') { + $date_to = $user_default_filter['date_to']; + } - if (io_safe_output($user_default_filter['tag_with']) != '[]' - && io_safe_output($user_default_filter['tag_with']) != '["0"]' - ) { - $tag_with = $user_default_filter['tag_with']; - $tag_with_clean = io_safe_output($tag_with); - $tag_with = json_decode($tag_with_clean, true); - } + if (io_safe_output($user_default_filter['tag_with']) != '[]' + && io_safe_output($user_default_filter['tag_with']) != '["0"]' + ) { + $tag_with = $user_default_filter['tag_with']; + $tag_with_clean = io_safe_output($tag_with); + $tag_with = json_decode($tag_with_clean, true); + } - if (io_safe_output($user_default_filter['tag_without']) != '[]' - && io_safe_output($user_default_filter['tag_without']) != '["0"]' - ) { - $tag_without = $user_default_filter['tag_without']; - $tag_without_clear = io_safe_output($tag_without); - $tag_without = json_decode($tag_without_clear, true); + if (io_safe_output($user_default_filter['tag_without']) != '[]' + && io_safe_output($user_default_filter['tag_without']) != '["0"]' + ) { + $tag_without = $user_default_filter['tag_without']; + $tag_without_clear = io_safe_output($tag_without); + $tag_without = json_decode($tag_without_clear, true); + } } } @@ -706,6 +708,9 @@ if (is_metaconsole()) { // Hidden field with the loaded filter name. $events_filter .= html_print_input_hidden('id_name', $id_name, true); +// Hidden field that signals filter has been applied. +$events_filter .= html_print_input_hidden('is_filtered', 'true', true); + // Hidden open filter flag // If autoupdate is in use collapse filter. if ($open_filter) { @@ -1039,6 +1044,20 @@ $events_filter .= $botom_update; $events_filter .= ''; // This is the filter div. +$user_filter = db_get_value( + 'default_event_filter', + 'tusuario', + 'id_user', + $config['id_user'] +); +$user_default_filter = db_get_all_rows_filter( + 'tevent_filter', + ['id_filter' => $user_filter] +); +$user_default_filter = $user_default_filter[0]; + +$id_name = $user_default_filter['id_name']; + $filter_resume['title'] = empty($id_name) ? __('No filter loaded') : __('Filter loaded').': '.$id_name; if (is_metaconsole()) { @@ -1321,8 +1340,6 @@ $(document).ready( function() { // Update the info with the loaded filter $('#filter_loaded_span').html($('#filter_loaded_text').html() + ': ' + $("#hidden-id_name").val()); - // Update the view with the loaded filter - $('#submit-update').trigger('click'); }, "json" ); diff --git a/pandora_console/operation/search_agents.getdata.php b/pandora_console/operation/search_agents.getdata.php index 5038800cf7..c754628731 100644 --- a/pandora_console/operation/search_agents.getdata.php +++ b/pandora_console/operation/search_agents.getdata.php @@ -182,7 +182,8 @@ if ($searchAgents) { } $sql = " - FROM tagente t1 + FROM tagente t1 LEFT JOIN tagent_secondary_group tasg + ON t1.id_agente = tasg.id_agent INNER JOIN tgrupo t2 ON t2.id_grupo = t1.id_grupo WHERE ( @@ -191,9 +192,11 @@ if ($searchAgents) { FROM tusuario WHERE id_user = '".$config['id_user']."' ) - OR t1.id_grupo IN ( - ".implode(',', $id_userGroups)." - ) OR 0 IN ( + OR ( + t1.id_grupo IN (".implode(',', $id_userGroups).') + OR tasg.id_group IN ('.implode(',', $id_userGroups).") + ) + OR 0 IN ( SELECT id_grupo FROM tusuario_perfil WHERE id_usuario = '".$config['id_user']."' @@ -208,7 +211,7 @@ if ($searchAgents) { ) '; - $select = 'SELECT t1.id_agente, t1.ultimo_contacto, t1.nombre, t1.id_os, t1.intervalo, t1.id_grupo, t1.disabled, t1.alias, t1.quiet'; + $select = 'SELECT DISTINCT(t1.id_agente), t1.ultimo_contacto, t1.nombre, t1.id_os, t1.intervalo, t1.id_grupo, t1.disabled, t1.alias, t1.quiet'; if ($only_count) { $limit = ' ORDER BY '.$order['field'].' '.$order['order'].' LIMIT '.$config['block_size'].' OFFSET 0'; } else { diff --git a/pandora_console/operation/search_modules.php b/pandora_console/operation/search_modules.php index 687dea13e2..bb86159035 100644 --- a/pandora_console/operation/search_modules.php +++ b/pandora_console/operation/search_modules.php @@ -108,6 +108,12 @@ if (!$modules || !$searchModules) { __('WARNING').': '.modules_get_last_value($module['id_agente_modulo']), true ); + } else if ($status_sql['estado'] == 3) { + $statusCell = ui_print_status_image( + STATUS_MODULE_UNKNOWN, + __('UNKNOWN').': '.modules_get_last_value($module['id_agente_modulo']), + true + ); } else { $last_status = modules_get_agentmodule_last_status($module['id_agente_modulo']); switch ($last_status) { diff --git a/pandora_console/operation/snmpconsole/snmp_mib_uploader.php b/pandora_console/operation/snmpconsole/snmp_mib_uploader.php index 7754fe3743..1fbe2b1823 100644 --- a/pandora_console/operation/snmpconsole/snmp_mib_uploader.php +++ b/pandora_console/operation/snmpconsole/snmp_mib_uploader.php @@ -69,9 +69,6 @@ $real_directory = realpath($config['homedir'].'/'.$directory); ui_print_info_message(__('MIB files will be installed on the system. Please note that a MIB may depend on other MIB. To customize trap definitions use the SNMP trap editor.')); -// echo '

      ' . __('Index of %s', $directory) . '

      '; -$homedir_filemanager = isset($config['homedir_filemanager']) ? $config['homedir_filemanager'] : false; - filemanager_file_explorer( $real_directory, $directory, @@ -82,5 +79,5 @@ filemanager_file_explorer( '', false, '', - $homedir_filemanager + false ); diff --git a/pandora_console/operation/visual_console/legacy_public_view.php b/pandora_console/operation/visual_console/legacy_public_view.php new file mode 100644 index 0000000000..18d8e2ca55 --- /dev/null +++ b/pandora_console/operation/visual_console/legacy_public_view.php @@ -0,0 +1,265 @@ +'."\n"; +echo ''."\n"; +echo ''; + +global $vc_public_view; +$vc_public_view = true; +// This starts the page head. In the call back function, +// things from $page['head'] array will be processed into the head +ob_start('ui_process_page_head'); +// Enterprise main +enterprise_include('index.php'); + +require_once 'include/functions_visual_map.php'; + +$hash = get_parameter('hash'); +$id_layout = (int) get_parameter('id_layout'); +$graph_javascript = (bool) get_parameter('graph_javascript'); +$config['id_user'] = get_parameter('id_user'); + +$myhash = md5($config['dbpass'].$id_layout.$config['id_user']); + +// Check input hash +if ($myhash != $hash) { + exit; +} + +$refr = (int) get_parameter('refr', 0); +$layout = db_get_row('tlayout', 'id', $id_layout); + +if (! $layout) { + db_pandora_audit('ACL Violation', 'Trying to access visual console without id layout'); + include $config['homedir'].'/general/noaccess.php'; + exit; +} + +if (!isset($config['pure'])) { + $config['pure'] = 0; +} + +// ~ $xhr = (bool) get_parameter('xhr'); +if ($layout) { + $id_group = $layout['id_group']; + $layout_name = $layout['name']; + $background = $layout['background']; + $bwidth = $layout['width']; + $bheight = $layout['height']; + // ~ $width = (int) get_parameter('width'); + // ~ if ($width <= 0) $width = null; + // ~ $height = (int) get_parameter('height'); + // ~ if ($height <= 0) $height = null; + // ~ ob_start(); + // ~ // Render map + visual_map_print_visual_map( + $id_layout, + true, + true, + $width, + $height, + '../../', + true, + true, + true + ); + // ~ return; +} else { + echo '
      '; +} + +// Floating menu - Start +echo '
      '; + +echo ''; + +echo '
      '; +// Floating menu - End +// QR code dialog +echo ''; + +ui_require_jquery_file('countdown'); +ui_require_javascript_file('wz_jsgraphics'); +ui_require_javascript_file('pandora_visual_console'); +$ignored_params['refr'] = ''; +?> + + + + diff --git a/pandora_console/operation/visual_console/legacy_view.php b/pandora_console/operation/visual_console/legacy_view.php new file mode 100644 index 0000000000..f5eec24096 --- /dev/null +++ b/pandora_console/operation/visual_console/legacy_view.php @@ -0,0 +1,386 @@ +'.html_print_image( + 'images/visual_console.png', + true, + ['title' => __('Visual consoles list')] +).''; + +if ($vconsole_write || $vconsole_manage) { + $url_base = 'index.php?sec=network&sec2=godmode/reporting/visual_console_builder&action='; + + $hash = md5($config['dbpass'].$id_layout.$config['id_user']); + + $options['public_link']['text'] = ''.html_print_image( + 'images/camera_mc.png', + true, + ['title' => __('Show link to public Visual Console')] + ).''; + $options['public_link']['active'] = false; + + $options['data']['text'] = ''.html_print_image( + 'images/op_reporting.png', + true, + ['title' => __('Main data')] + ).''; + $options['list_elements']['text'] = ''.html_print_image( + 'images/list.png', + true, + ['title' => __('List elements')] + ).''; + + if (enterprise_installed()) { + $options['wizard_services']['text'] = ''.html_print_image( + 'images/wand_services.png', + true, + ['title' => __('Services wizard')] + ).''; + } + + $options['wizard']['text'] = ''.html_print_image( + 'images/wand.png', + true, + ['title' => __('Wizard')] + ).''; + $options['editor']['text'] = ''.html_print_image( + 'images/builder.png', + true, + ['title' => __('Builder')] + ).''; +} + +$options['view']['text'] = ''.html_print_image('images/operation.png', true, ['title' => __('View')]).''; +$options['view']['active'] = true; + +if (!is_metaconsole()) { + if (!$config['pure']) { + $options['pure']['text'] = ''.html_print_image('images/full_screen.png', true, ['title' => __('Full screen mode')]).''; + ui_print_page_header($layout_name, 'images/visual_console.png', false, '', false, $options); + } + + // Set the hidden value for the javascript + html_print_input_hidden('metaconsole', 0); +} else { + // Set the hidden value for the javascript + html_print_input_hidden('metaconsole', 1); +} + +if ($config['pure']) { + // Container of the visual map (ajax loaded) + echo '
      '.visual_map_print_visual_map( + $id_layout, + true, + true, + null, + null, + '', + false, + true + ).'
      '; + + // Floating menu - Start + echo '
      '; + + echo ''; + + echo '
      '; + // Floating menu - End + ui_require_jquery_file('countdown'); + + ?> + + + + + + \ No newline at end of file diff --git a/pandora_console/operation/visual_console/public_console.php b/pandora_console/operation/visual_console/public_console.php index bc5b3d2a20..8a6ff462fc 100755 --- a/pandora_console/operation/visual_console/public_console.php +++ b/pandora_console/operation/visual_console/public_console.php @@ -15,245 +15,9 @@ // The session is configured and started inside the config process. require_once '../../include/config.php'; -// Set root on homedir, as defined in setup -chdir($config['homedir']); - -ob_start(); -// Enterprise support -if (file_exists(ENTERPRISE_DIR.'/load_enterprise.php')) { - include_once ENTERPRISE_DIR.'/load_enterprise.php'; -} - -if (file_exists(ENTERPRISE_DIR.'/include/functions_login.php')) { - include_once ENTERPRISE_DIR.'/include/functions_login.php'; -} - -echo ''."\n"; -echo ''."\n"; -echo ''; - -global $vc_public_view; -$vc_public_view = true; -// This starts the page head. In the call back function, -// things from $page['head'] array will be processed into the head -ob_start('ui_process_page_head'); -// Enterprise main -enterprise_include('index.php'); - -require_once 'include/functions_visual_map.php'; - -$hash = get_parameter('hash'); -$id_layout = (int) get_parameter('id_layout'); -$graph_javascript = (bool) get_parameter('graph_javascript'); -$config['id_user'] = get_parameter('id_user'); - -$myhash = md5($config['dbpass'].$id_layout.$config['id_user']); - -// Check input hash -if ($myhash != $hash) { - exit; -} - -$refr = (int) get_parameter('refr', 0); -$layout = db_get_row('tlayout', 'id', $id_layout); - -if (! $layout) { - db_pandora_audit('ACL Violation', 'Trying to access visual console without id layout'); - include $config['homedir'].'/general/noaccess.php'; - exit; -} - -if (!isset($config['pure'])) { - $config['pure'] = 0; -} - -// ~ $xhr = (bool) get_parameter('xhr'); -if ($layout) { - $id_group = $layout['id_group']; - $layout_name = $layout['name']; - $background = $layout['background']; - $bwidth = $layout['width']; - $bheight = $layout['height']; - // ~ $width = (int) get_parameter('width'); - // ~ if ($width <= 0) $width = null; - // ~ $height = (int) get_parameter('height'); - // ~ if ($height <= 0) $height = null; - // ~ ob_start(); - // ~ // Render map - visual_map_print_visual_map( - $id_layout, - true, - true, - $width, - $height, - '../../', - true, - true, - true - ); - // ~ return; +$legacy = (bool) get_parameter('legacy', $config['legacy_vc']); +if ($legacy === false) { + include_once $config['homedir'].'/operation/visual_console/public_view.php'; } else { - echo '
      '; + include_once $config['homedir'].'/operation/visual_console/legacy_public_view.php'; } - -// Floating menu - Start -echo '
      '; - -echo ''; - -echo '
      '; -// Floating menu - End -// QR code dialog -echo ''; - -ui_require_jquery_file('countdown'); -ui_require_javascript_file('wz_jsgraphics'); -ui_require_javascript_file('pandora_visual_console'); -$ignored_params['refr'] = ''; -?> - - diff --git a/pandora_console/operation/visual_console/public_view.php b/pandora_console/operation/visual_console/public_view.php new file mode 100644 index 0000000000..0a23c5f216 --- /dev/null +++ b/pandora_console/operation/visual_console/public_view.php @@ -0,0 +1,209 @@ +'."\n"; +echo ''."\n"; +echo ''; + +global $vc_public_view; +$vc_public_view = true; +$config['public_view'] = true; + +// This starts the page head. In the call back function, +// things from $page['head'] array will be processed into the head. +ob_start('ui_process_page_head'); +// Enterprise main. +enterprise_include('index.php'); + +require_once 'include/functions_visual_map.php'; + +$hash = (string) get_parameter('hash'); +$visualConsoleId = (int) get_parameter('id_layout'); +$config['id_user'] = (string) get_parameter('id_user'); +$refr = (int) get_parameter('refr', $config['refr']); + +if (!isset($config['pure'])) { + $config['pure'] = 0; +} + +$myhash = md5($config['dbpass'].$visualConsoleId.$config['id_user']); + +// Check input hash. +if ($myhash != $hash) { + exit; +} + +// Load Visual Console. +use Models\VisualConsole\Container as VisualConsole; +$visualConsole = null; +try { + $visualConsole = VisualConsole::fromDB(['id' => $visualConsoleId]); +} catch (Throwable $e) { + db_pandora_audit( + 'ACL Violation', + 'Trying to access visual console without Id' + ); + include $config['homedir'].'/general/noaccess.php'; + exit; +} + +$visualConsoleData = $visualConsole->toArray(); +$visualConsoleName = $visualConsoleData['name']; + +echo '
      '; + +// Floating menu - Start. +echo '
      '; + +echo ''; + +echo '
      '; + +// QR code dialog. +echo ''; + +// Check groups can access user. +$aclUserGroups = []; +if (!users_can_manage_group_all('AR')) { + $aclUserGroups = array_keys(users_get_groups(false, 'AR')); +} + +$ignored_params['refr'] = ''; +ui_require_javascript_file('pandora_visual_console'); +include_javascript_d3(); +visual_map_load_client_resources(); + +// Load Visual Console Items. +$visualConsoleItems = VisualConsole::getItemsFromDB( + $visualConsoleId, + $aclUserGroups +); + +?> + + + + diff --git a/pandora_console/operation/visual_console/render_view.php b/pandora_console/operation/visual_console/render_view.php index 4799932e2c..00cdc2d113 100755 --- a/pandora_console/operation/visual_console/render_view.php +++ b/pandora_console/operation/visual_console/render_view.php @@ -13,368 +13,9 @@ // GNU General Public License for more details. global $config; -// Login check -require_once $config['homedir'].'/include/functions_visual_map.php'; - -check_login(); - -if (!defined('METACONSOLE')) { - $id_layout = (int) get_parameter('id'); +$legacy = (bool) get_parameter('legacy', $config['legacy_vc']); +if ($legacy === false) { + include_once $config['homedir'].'/operation/visual_console/view.php'; } else { - $id_layout = (int) get_parameter('id_visualmap'); + include_once $config['homedir'].'/operation/visual_console/legacy_view.php'; } - -if ($id_layout) { - $default_action = 'edit'; -} else { - $default_action = 'new'; -} - -if (!defined('METACONSOLE')) { - $action = get_parameterBetweenListValues( - 'action', - [ - 'new', - 'save', - 'edit', - 'update', - 'delete', - ], - $default_action - ); -} else { - $action = get_parameterBetweenListValues( - 'action2', - [ - 'new', - 'save', - 'edit', - 'update', - 'delete', - ], - $default_action - ); -} - -$refr = (int) get_parameter('refr', $config['vc_refr']); -$graph_javascript = (bool) get_parameter('graph_javascript', true); -$vc_refr = false; - -if (isset($config['vc_refr']) and $config['vc_refr'] != 0) { - $view_refresh = $config['vc_refr']; -} else { - $view_refresh = '300'; -} - -// Get input parameter for layout id -if (! $id_layout) { - db_pandora_audit( - 'ACL Violation', - 'Trying to access visual console without id layout' - ); - include 'general/noaccess.php'; - exit; -} - -$layout = db_get_row('tlayout', 'id', $id_layout); - -if (! $layout) { - db_pandora_audit( - 'ACL Violation', - 'Trying to access visual console without id layout' - ); - include 'general/noaccess.php'; - exit; -} - -$id_group = $layout['id_group']; -$layout_name = $layout['name']; -$background = $layout['background']; -$bwidth = $layout['width']; -$bheight = $layout['height']; - -$pure_url = '&pure='.$config['pure']; - -// ACL -$vconsole_read = check_acl($config['id_user'], $id_group, 'VR'); -$vconsole_write = check_acl($config['id_user'], $id_group, 'VW'); -$vconsole_manage = check_acl($config['id_user'], $id_group, 'VM'); - -if (! $vconsole_read && !$vconsole_write && !$vconsole_manage) { - db_pandora_audit( - 'ACL Violation', - 'Trying to access visual console without group access' - ); - include 'general/noaccess.php'; - exit; -} - -// Render map -$options = []; - -$options['consoles_list']['text'] = ''.html_print_image( - 'images/visual_console.png', - true, - ['title' => __('Visual consoles list')] -).''; - -if ($vconsole_write || $vconsole_manage) { - $url_base = 'index.php?sec=network&sec2=godmode/reporting/visual_console_builder&action='; - - $hash = md5($config['dbpass'].$id_layout.$config['id_user']); - - $options['public_link']['text'] = ''.html_print_image( - 'images/camera_mc.png', - true, - ['title' => __('Show link to public Visual Console')] - ).''; - $options['public_link']['active'] = false; - - $options['data']['text'] = ''.html_print_image( - 'images/op_reporting.png', - true, - ['title' => __('Main data')] - ).''; - $options['list_elements']['text'] = ''.html_print_image( - 'images/list.png', - true, - ['title' => __('List elements')] - ).''; - - if (enterprise_installed()) { - $options['wizard_services']['text'] = ''.html_print_image( - 'images/wand_services.png', - true, - ['title' => __('Services wizard')] - ).''; - } - - $options['wizard']['text'] = ''.html_print_image( - 'images/wand.png', - true, - ['title' => __('Wizard')] - ).''; - $options['editor']['text'] = ''.html_print_image( - 'images/builder.png', - true, - ['title' => __('Builder')] - ).''; -} - -$options['view']['text'] = ''.html_print_image('images/operation.png', true, ['title' => __('View')]).''; -$options['view']['active'] = true; - -if (!is_metaconsole()) { - if (!$config['pure']) { - $options['pure']['text'] = ''.html_print_image('images/full_screen.png', true, ['title' => __('Full screen mode')]).''; - ui_print_page_header($layout_name, 'images/visual_console.png', false, '', false, $options); - } - - // Set the hidden value for the javascript - html_print_input_hidden('metaconsole', 0); -} else { - // Set the hidden value for the javascript - html_print_input_hidden('metaconsole', 1); -} - -if ($config['pure']) { - // Container of the visual map (ajax loaded) - echo '
      '.visual_map_print_visual_map( - $id_layout, - true, - true, - null, - null, - '', - false, - true - ).'
      '; - - // Floating menu - Start - echo '
      '; - - echo ''; - - echo '
      '; - // Floating menu - End - ui_require_jquery_file('countdown'); - - ?> - - - - \ No newline at end of file diff --git a/pandora_console/operation/visual_console/view.php b/pandora_console/operation/visual_console/view.php new file mode 100644 index 0000000000..5134c0d98d --- /dev/null +++ b/pandora_console/operation/visual_console/view.php @@ -0,0 +1,320 @@ + $visualConsoleId]); +} catch (Throwable $e) { + db_pandora_audit( + 'ACL Violation', + 'Trying to access visual console without Id' + ); + include 'general/noaccess.php'; + exit; +} + +$visualConsoleData = $visualConsole->toArray(); +$groupId = $visualConsoleData['groupId']; +$visualConsoleName = $visualConsoleData['name']; + +// ACL. +$aclRead = check_acl($config['id_user'], $groupId, 'VR'); +$aclWrite = check_acl($config['id_user'], $groupId, 'VW'); +$aclManage = check_acl($config['id_user'], $groupId, 'VM'); + +if (!$aclRead && !$aclWrite && !$aclManage) { + db_pandora_audit( + 'ACL Violation', + 'Trying to access visual console without group access' + ); + include 'general/noaccess.php'; + exit; +} + +// Render map. +$options = []; + +$options['consoles_list']['text'] = ''.html_print_image( + 'images/visual_console.png', + true, + ['title' => __('Visual consoles list')] +).''; + +if ($aclWrite || $aclManage) { + $action = get_parameterBetweenListValues( + is_metaconsole() ? 'action2' : 'action', + [ + 'new', + 'save', + 'edit', + 'update', + 'delete', + ], + 'edit' + ); + + $baseUrl = 'index.php?sec=network&sec2=godmode/reporting/visual_console_builder&action='.$action; + + $hash = md5($config['dbpass'].$visualConsoleId.$config['id_user']); + + $options['public_link']['text'] = ''.html_print_image( + 'images/camera_mc.png', + true, + ['title' => __('Show link to public Visual Console')] + ).''; + $options['public_link']['active'] = false; + + $options['data']['text'] = ''.html_print_image( + 'images/op_reporting.png', + true, + ['title' => __('Main data')] + ).''; + $options['list_elements']['text'] = ''.html_print_image( + 'images/list.png', + true, + ['title' => __('List elements')] + ).''; + + if (enterprise_installed()) { + $options['wizard_services']['text'] = ''.html_print_image( + 'images/wand_services.png', + true, + ['title' => __('Services wizard')] + ).''; + } + + $options['wizard']['text'] = ''.html_print_image( + 'images/wand.png', + true, + ['title' => __('Wizard')] + ).''; + $options['editor']['text'] = ''.html_print_image( + 'images/builder.png', + true, + ['title' => __('Builder')] + ).''; +} + +$options['view']['text'] = ''.html_print_image( + 'images/operation.png', + true, + ['title' => __('View')] +).''; +$options['view']['active'] = true; + +if (!is_metaconsole()) { + if (!$config['pure']) { + $options['pure']['text'] = ''.html_print_image( + 'images/full_screen.png', + true, + ['title' => __('Full screen mode')] + ).''; + ui_print_page_header( + $visualConsoleName, + 'images/visual_console.png', + false, + '', + false, + $options + ); + } + + // Set the hidden value for the javascript. + html_print_input_hidden('metaconsole', 0); +} else { + // Set the hidden value for the javascript. + html_print_input_hidden('metaconsole', 1); +} + +echo '
      '; + +if ($pure === true) { + // Floating menu - Start. + echo '
      '; + + echo ''; + + echo '
      '; + // Floating menu - End. + ?> + + + + diff --git a/pandora_console/pandora_console.redhat.spec b/pandora_console/pandora_console.redhat.spec index 79b6a741c4..0efbf2c140 100644 --- a/pandora_console/pandora_console.redhat.spec +++ b/pandora_console/pandora_console.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.734 -%define release 190425 +%define release 190513 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.rhel7.spec b/pandora_console/pandora_console.rhel7.spec index e8d9ea95cd..56c5bae799 100644 --- a/pandora_console/pandora_console.rhel7.spec +++ b/pandora_console/pandora_console.rhel7.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.734 -%define release 190425 +%define release 190513 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.spec b/pandora_console/pandora_console.spec index 2746a6e46f..c1a6b4a1a2 100644 --- a/pandora_console/pandora_console.spec +++ b/pandora_console/pandora_console.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.734 -%define release 190425 +%define release 190513 %define httpd_name httpd # User and Group under which Apache is running %define httpd_name apache2 diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 97db7b4098..760e9512f6 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -449,7 +449,7 @@ CREATE TABLE IF NOT EXISTS `talert_templates` ( `field13` text NOT NULL, `field14` text NOT NULL, `field15` text NOT NULL, - `type` ENUM ('regex', 'max_min', 'max', 'min', 'equal', 'not_equal', 'warning', 'critical', 'onchange', 'unknown', 'always'), + `type` ENUM ('regex', 'max_min', 'max', 'min', 'equal', 'not_equal', 'warning', 'critical', 'onchange', 'unknown', 'always', 'not_normal'), `value` varchar(255) default '', `matches_value` tinyint(1) default 0, `max_value` double(18,2) default NULL, @@ -1422,6 +1422,18 @@ CREATE TABLE IF NOT EXISTS `treport_content` ( `hide_no_data` tinyint(1) default 0, `recursion` tinyint(1) default NULL, `show_extended_events` tinyint(1) default '0', + `total_time` TINYINT(1) DEFAULT '1', + `time_failed` TINYINT(1) DEFAULT '1', + `time_in_ok_status` TINYINT(1) DEFAULT '1', + `time_in_unknown_status` TINYINT(1) DEFAULT '1', + `time_of_not_initialized_module` TINYINT(1) DEFAULT '1', + `time_of_downtime` TINYINT(1) DEFAULT '1', + `total_checks` TINYINT(1) DEFAULT '1', + `checks_failed` TINYINT(1) DEFAULT '1', + `checks_in_ok_status` TINYINT(1) DEFAULT '1', + `unknown_checks` TINYINT(1) DEFAULT '1', + `agent_max_value` TINYINT(1) DEFAULT '1', + `agent_min_value` TINYINT(1) DEFAULT '1', PRIMARY KEY(`id_rc`), FOREIGN KEY (`id_report`) REFERENCES treport(`id_report`) ON UPDATE CASCADE ON DELETE CASCADE @@ -2949,6 +2961,18 @@ CREATE TABLE IF NOT EXISTS `treport_content_template` ( `lapse` int(11) UNSIGNED NOT NULL default '300', `visual_format` tinyint(1) UNSIGNED NOT NULL default '0', `hide_no_data` tinyint(1) default 0, + `total_time` TINYINT(1) DEFAULT '1', + `time_failed` TINYINT(1) DEFAULT '1', + `time_in_ok_status` TINYINT(1) DEFAULT '1', + `time_in_unknown_status` TINYINT(1) DEFAULT '1', + `time_of_not_initialized_module` TINYINT(1) DEFAULT '1', + `time_of_downtime` TINYINT(1) DEFAULT '1', + `total_checks` TINYINT(1) DEFAULT '1', + `checks_failed` TINYINT(1) DEFAULT '1', + `checks_in_ok_status` TINYINT(1) DEFAULT '1', + `unknown_checks` TINYINT(1) DEFAULT '1', + `agent_max_value` TINYINT(1) DEFAULT '1', + `agent_min_value` TINYINT(1) DEFAULT '1', PRIMARY KEY(`id_rc`) ) ENGINE = InnoDB DEFAULT CHARSET=utf8; diff --git a/pandora_console/pandoradb_data.sql b/pandora_console/pandoradb_data.sql index 7b9517f661..a07d040306 100644 --- a/pandora_console/pandoradb_data.sql +++ b/pandora_console/pandoradb_data.sql @@ -114,10 +114,10 @@ INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_report_front_logo', 'images/pandora_logo_white.jpg'), ('custom_report_front_header', ''), ('custom_report_front_footer', ''), -('MR', 27), +('MR', 28), ('identification_reminder', 1), ('identification_reminder_timestamp', 0), -('current_package_enterprise', '734'), +('current_package_enterprise', '735'), ('post_process_custom_values', '{"0.00000038580247":"Seconds to months","0.00000165343915":"Seconds to weeks","0.00001157407407":"Seconds to days","0.01666666666667":"Seconds to minutes","0.00000000093132":"Bytes to Gigabytes","0.00000095367432":"Bytes to Megabytes","0.0009765625":"Bytes to Kilobytes","0.00000001653439":"Timeticks to weeks","0.00000011574074":"Timeticks to days"}'), ('custom_docs_logo', 'default_docs.png'), ('custom_support_logo', 'default_support.png'), @@ -1158,7 +1158,7 @@ INSERT INTO `tagent_custom_fields` VALUES (1,'Serial Number',0,0,''),(2,'De INSERT INTO `ttag` VALUES (1,'network','Network equipment','http://artica.es','',''),(2,'critical','Critical modules','','',''),(3,'dmz','DMZ Network Zone','','',''),(4,'performance','Performance anda capacity modules','','',''),(5,'configuration','','','',''); -INSERT INTO `tevent_response` VALUES (1,'Ping to host','Ping to the agent host','ping -c 5 _agent_address_','command',0,620,500,0,'',0),(3,'Create incident from event','Create a incident from the event with the standard incidents system of Pandora FMS','index.php?sec=workspace&sec2=operation/incidents/incident_detail&insert_form&from_event=_event_id_','url',0,0,0,1,'',0),(4,'Create Integria IMS incident from event','Create a incident from the event with integria incidents system of Pandora FMS. Is necessary to enable and configure the Integria incidents in Pandora FMS setup.','index.php?sec=workspace&sec2=operation/integria_incidents/incident&tab=editor&from_event=_event_id_','url',0,0,0,1,'',0),(5,'Restart agent','Restart the agent with using UDP protocol. To use this response is necessary to have installed Pandora FMS server and console in the same machine.','/usr/share/pandora_server/util/udp_client.pl _agent_address_ 41122 "REFRESH AGENT"','command',0,620,500,0,'',0),(6,'Ping to module agent host','Ping to the module agent host','ping -c 5 _module_address_','command',0,620,500,0,'',0); +INSERT INTO `tevent_response` VALUES (1,'Ping to host','Ping to the agent host','ping -c 5 _agent_address_','command',0,620,500,0,'',0),(3,'Create incident from event','Create a incident from the event with the standard incidents system of Pandora FMS','index.php?sec=workspace&sec2=operation/incidents/incident_detail&insert_form&from_event=_event_id_','url',0,0,0,1,'',0),(5,'Restart agent','Restart the agent with using UDP protocol. To use this response is necessary to have installed Pandora FMS server and console in the same machine.','/usr/share/pandora_server/util/udp_client.pl _agent_address_ 41122 "REFRESH AGENT"','command',0,620,500,0,'',0),(6,'Ping to module agent host','Ping to the module agent host','ping -c 5 _module_address_','command',0,620,500,0,'',0); INSERT INTO `tupdate_settings` VALUES ('current_update', '412'), ('customer_key', 'PANDORA-FREE'), ('updating_binary_path', 'Path where the updated binary files will be stored'), ('updating_code_path', 'Path where the updated code is stored'), ('dbname', ''), ('dbhost', ''), ('dbpass', ''), ('dbuser', ''), ('dbport', ''), ('proxy', ''), ('proxy_port', ''), ('proxy_user', ''), ('proxy_pass', ''); @@ -1315,4 +1315,4 @@ INSERT INTO `tnotification_source_user`(`id_source`,`id_user`,`enabled`,`also_ma INSERT INTO `tnotification_source_group` SELECT `id`,0 FROM `tnotification_source` WHERE `description`="Message"; - \ No newline at end of file + diff --git a/pandora_console/tests/Functional/Models/VisualConsole/ContainerTest.php b/pandora_console/tests/Functional/Models/VisualConsole/ContainerTest.php new file mode 100644 index 0000000000..b7a1a7c6de --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/ContainerTest.php @@ -0,0 +1,268 @@ +assertInstanceOf( + VisualConsole::class, + VisualConsole::fromArray( + [ + 'id' => 1, + 'name' => 'foo', + 'groupId' => 1, + 'backgroundURL' => 'aaa', + 'backgroundColor' => 'bbb', + 'width' => 800, + 'height' => 800, + ] + ) + ); + + $this->assertInstanceOf( + VisualConsole::class, + VisualConsole::fromArray( + [ + 'id' => 69, + 'name' => 'New visual console', + 'groupId' => 0, + 'background' => 'globalmap.jpg', + 'background_color' => 'white', + 'is_favourite' => 1, + 'width' => 100, + 'height' => 200, + ] + ) + ); + + $this->assertInstanceOf( + VisualConsole::class, + VisualConsole::fromArray( + [ + 'id' => 1030, + 'name' => 'console2', + 'groupId' => 12, + 'width' => 1024, + 'height' => 768, + ] + ) + ); + } + + + /** + * Test if the instance is not created when using a invalid id. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidId(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid id. + VisualConsole::fromArray( + [ + 'id' => 'bar', + 'name' => 'foo', + 'groupId' => 0, + 'is_favourite' => 1, + 'width' => 1024, + 'height' => 768, + ] + ); + // Missing id. + VisualConsole::fromArray( + [ + 'name' => 'foo', + 'groupId' => 0, + 'width' => 1024, + 'height' => 768, + ] + ); + } + + + /** + * Test if the instance is not created when using a invalid name. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidName(): void + { + $this->expectException(InvalidArgumentException::class); + // Empty name. + VisualConsole::fromArray( + [ + 'id' => 1, + 'name' => '', + 'groupId' => 0, + 'width' => 1024, + 'height' => 768, + ] + ); + // Missing name. + VisualConsole::fromArray( + [ + 'id' => 1, + 'groupId' => 8, + 'width' => 1024, + 'height' => 768, + ] + ); + } + + + /** + * Test if the instance is not created when using a invalid group id. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidGroupId(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid group id. + VisualConsole::fromArray( + [ + 'id' => 1, + 'name' => 'test', + 'groupId' => 'Hi', + 'width' => 1024, + 'height' => 768, + ] + ); + + // Missing group id. + VisualConsole::fromArray( + [ + 'id' => 1, + 'name' => 'test', + 'width' => 1024, + 'height' => 768, + ] + ); + } + + + /** + * Test if the instance is not created when using a invalid width. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidWidth(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid width. + VisualConsole::fromArray( + [ + 'id' => 1, + 'name' => 'test', + 'groupId' => 10, + 'width' => 0, + 'height' => 768, + ] + ); + + // Missing width. + VisualConsole::fromArray( + [ + 'id' => 1, + 'name' => 'test', + 'groupId' => 10, + 'height' => 768, + ] + ); + } + + + /** + * Test if the instance is not created when using a invalid height. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidHeigth(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid height. + VisualConsole::fromArray( + [ + 'id' => 1, + 'name' => 'test', + 'groupId' => 10, + 'width' => 1024, + 'height' => -1, + ] + ); + + // Missing height. + VisualConsole::fromArray( + [ + 'id' => 1, + 'name' => 'test', + 'groupId' => 10, + 'width' => 1024, + ] + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"backgroundColor":null,"backgroundURL":null,"groupId":0,"height":768,"id":1,"isFavorite":false,"name":"foo","width":1024}', + (string) VisualConsole::fromArray( + [ + 'id' => 1, + 'name' => 'foo', + 'groupId' => 0, + 'width' => 1024, + 'height' => 768, + ] + ) + ); + } + + + /** + * Test if the item's instance is returned properly. + * + * @return void + */ + public function testItemClassIsReturned(): void + { + $this->assertEquals( + VisualConsole::getItemClass(STATIC_GRAPH), + Models\VisualConsole\Items\StaticGraph::class + ); + + $this->assertEquals( + VisualConsole::getItemClass(COLOR_CLOUD), + Models\VisualConsole\Items\ColorCloud::class + ); + + $this->assertEquals( + VisualConsole::getItemClass(LABEL), + Models\VisualConsole\Items\Label::class + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/ItemTest.php b/pandora_console/tests/Functional/Models/VisualConsole/ItemTest.php new file mode 100644 index 0000000000..b4b5dea59b --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/ItemTest.php @@ -0,0 +1,298 @@ +assertInstanceOf( + ItemConsole::class, + ItemConsole::fromArray( + [ + 'id' => 1, + 'type' => 5, + 'label' => 'test', + 'labelPosition' => 'down', + 'isLinkEnabled' => false, + 'isOnTop' => true, + 'parentId' => 0, + 'aclGroupId' => 12, + 'width' => 800, + 'height' => 600, + 'x' => 0, + 'y' => 0, + ] + ) + ); + + $this->assertInstanceOf( + ItemConsole::class, + ItemConsole::fromArray( + [ + 'id' => 1, + 'type' => 5, + 'width' => 0, + 'height' => 0, + ] + ) + ); + } + + + /** + * Test if the instance is not created when using a invalid id. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidId(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid id. + ItemConsole::fromArray( + [ + 'id' => 'foo', + 'type' => 5, + 'label' => 'test', + 'labelPosition' => 'down', + 'isLinkEnabled' => false, + 'isOnTop' => true, + 'parentId' => 0, + 'aclGroupId' => 12, + 'width' => 800, + 'height' => 600, + 'x' => 0, + 'y' => 0, + ] + ); + // Missing id. + ItemConsole::fromArray( + [ + 'type' => 5, + 'label' => 'test', + 'labelPosition' => 'down', + 'isLinkEnabled' => false, + 'isOnTop' => true, + 'parentId' => 0, + 'aclGroupId' => 12, + 'width' => 800, + 'height' => 600, + 'x' => 0, + 'y' => 0, + ] + ); + } + + + /** + * Test if the instance is not created when using a invalid type. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidType(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid id. + ItemConsole::fromArray( + [ + 'id' => 15, + 'type' => 'clock', + 'label' => 'test', + 'labelPosition' => 'down', + 'isLinkEnabled' => false, + 'isOnTop' => true, + 'parentId' => 0, + 'aclGroupId' => 12, + 'width' => 800, + 'height' => 600, + 'x' => 0, + 'y' => 0, + ] + ); + // Missing id. + ItemConsole::fromArray( + [ + 'id' => 6, + 'label' => 'test', + 'labelPosition' => 'down', + 'isLinkEnabled' => false, + 'isOnTop' => true, + 'parentId' => 0, + 'aclGroupId' => 12, + 'width' => 800, + 'height' => 600, + 'x' => 0, + 'y' => 0, + ] + ); + } + + + /** + * Test if the instance is not created when using a invalid width. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidWidth(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid id. + ItemConsole::fromArray( + [ + 'id' => 15, + 'type' => 3, + 'label' => 'test', + 'labelPosition' => 'down', + 'isLinkEnabled' => false, + 'isOnTop' => true, + 'parentId' => 0, + 'aclGroupId' => 12, + 'width' => -1, + 'height' => 600, + 'x' => 0, + 'y' => 0, + ] + ); + // Missing id. + ItemConsole::fromArray( + [ + 'id' => 15, + 'type' => 3, + 'label' => 'test', + 'labelPosition' => 'down', + 'isLinkEnabled' => false, + 'isOnTop' => true, + 'parentId' => 0, + 'aclGroupId' => 12, + 'height' => 600, + 'x' => 0, + 'y' => 0, + ] + ); + } + + + /** + * Test if the instance is not created when using a invalid height. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidHeight(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid id. + ItemConsole::fromArray( + [ + 'id' => 15, + 'type' => 3, + 'label' => 'test', + 'labelPosition' => 'down', + 'isLinkEnabled' => false, + 'isOnTop' => true, + 'parentId' => 0, + 'aclGroupId' => 12, + 'width' => 800, + 'height' => -1, + 'x' => 0, + 'y' => 0, + ] + ); + // Missing id. + ItemConsole::fromArray( + [ + 'id' => 15, + 'type' => 3, + 'label' => 'test', + 'labelPosition' => 'down', + 'isLinkEnabled' => false, + 'isOnTop' => true, + 'parentId' => 0, + 'aclGroupId' => 12, + 'width' => 600, + 'x' => 0, + 'y' => 0, + ] + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testItemIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":12,"height":600,"id":15,"isLinkEnabled":false,"isOnTop":true,"label":"test","labelPosition":"down","parentId":0,"type":3,"width":800,"x":0,"y":0}', + (string) ItemConsole::fromArray( + [ + 'id' => 15, + 'type' => 3, + 'label' => 'test', + 'labelPosition' => 'down', + 'isLinkEnabled' => false, + 'isOnTop' => true, + 'parentId' => 0, + 'aclGroupId' => 12, + 'width' => 800, + 'height' => 600, + 'x' => 0, + 'y' => 0, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":12,"height":600,"id":15,"isLinkEnabled":false,"isOnTop":false,"label":null,"labelPosition":"down","parentId":0,"type":3,"width":800,"x":0,"y":0}', + (string) ItemConsole::fromArray( + [ + 'id' => 15, + 'type' => 3, + 'label' => '', + 'labelPosition' => 'test', + 'parentId' => 0, + 'aclGroupId' => 12, + 'width' => 800, + 'height' => 600, + 'x' => 0, + 'y' => 0, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"height":0,"id":69,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","parentId":null,"type":20,"width":0,"x":-666,"y":76}', + (string) ItemConsole::fromArray( + [ + 'id' => 69, + 'type' => 20, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + ] + ) + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/BarsGraphTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/BarsGraphTest.php new file mode 100644 index 0000000000..16866a4fc6 --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/BarsGraphTest.php @@ -0,0 +1,111 @@ +assertInstanceOf( + BarsGraph::class, + BarsGraph::fromArray( + [ + 'id' => 7, + 'type' => BARS_GRAPH, + 'width' => '600', + 'height' => '500', + 'typeGraph' => 'horizontal', + 'backgroundColor' => 'white', + 'gridColor' => '#33CCFF', + 'encodedHtml' => '

      Foo

      ', + ] + ) + ); + + $this->assertInstanceOf( + BarsGraph::class, + BarsGraph::fromArray( + [ + 'id' => 23, + 'type' => BARS_GRAPH, + 'width' => '800', + 'height' => '600', + 'type_graph' => 'vertical', + 'image' => 'transparent', + 'border_color' => '#33CCFF', + 'html' => '

      Foo

      ', + ] + ) + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"backgroundColor":"transparent","encodedHtml":"PGgxPkZvbzwvaDE+","gridColor":"#33CCFF","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","moduleId":null,"moduleName":null,"parentId":null,"type":18,"typeGraph":"vertical","width":0,"x":-666,"y":76}', + (string) BarsGraph::fromArray( + [ + 'id' => 7, + 'type' => DONUT_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'type_graph' => 'vertical', + 'image' => 'transparent', + 'border_color' => '#33CCFF', + 'html' => '

      Foo

      ', + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"backgroundColor":"white","encodedHtml":"PGgxPkZvbzwvaDE+","gridColor":"#33CCFF","height":300,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":"test","labelPosition":"left","moduleId":null,"moduleName":null,"parentId":null,"type":18,"typeGraph":"horizontal","width":300,"x":-666,"y":76}', + (string) BarsGraph::fromArray( + [ + 'id' => 7, + 'type' => DONUT_GRAPH, + 'label' => 'test', + 'labelPosition' => 'left', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '300', + 'height' => '300', + 'x' => -666, + 'y' => 76, + 'typeGraph' => 'horizontal', + 'backgroundColor' => 'white', + 'gridColor' => '#33CCFF', + 'encodedHtml' => 'PGgxPkZvbzwvaDE+', + ] + ) + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/BoxTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/BoxTest.php new file mode 100644 index 0000000000..9d2e0b2f4d --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/BoxTest.php @@ -0,0 +1,84 @@ +assertInstanceOf( + Box::class, + Box::fromArray( + [ + 'id' => 69, + 'type' => 12, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + ] + ) + ); + + $this->assertInstanceOf( + Box::class, + Box::fromArray( + [ + 'id' => 1000, + 'type' => 8, + 'name' => 'test', + 'width' => 100, + 'height' => 900, + ] + ) + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"borderColor":null,"borderWidth":0,"fillColor":null,"height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","parentId":null,"type":12,"width":0,"x":-666,"y":76}', + (string) Box::fromArray( + [ + 'id' => 7, + 'type' => 10, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + ] + ) + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/ClockTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/ClockTest.php new file mode 100644 index 0000000000..269bb7bef5 --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/ClockTest.php @@ -0,0 +1,173 @@ +assertInstanceOf( + Clock::class, + Clock::fromArray( + [ + 'id' => 69, + 'type' => CLOCK, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'clockType' => 'digital', + 'clockFormat' => 'time', + 'clockTimezone' => 'Europe/Madrid', + 'showClockTimezone' => false, + 'color' => 'white', + ] + ) + ); + + $this->assertInstanceOf( + Clock::class, + Clock::fromArray( + [ + 'id' => 1000, + 'type' => CLOCK, + 'width' => 100, + 'height' => 900, + 'clockType' => 'analogic', + 'clockFormat' => 'datetime', + 'clockTimezone' => 'Asia/Tokyo', + 'showClockTimezone' => true, + 'color' => 'red', + ] + ) + ); + } + + + /** + * Test if the instance is not created when using a invalid clockTimezone. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidClockTimezone(): void + { + $this->expectException(Exception::class); + // Invalid clockTimezone. + Clock::fromArray( + [ + 'id' => 69, + 'type' => CLOCK, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'clockType' => 'digital', + 'clockFormat' => 'time', + 'clockTimezone' => 'Europe/Tokyo', + 'showClockTimezone' => false, + 'color' => 'white', + ] + ); + + // Invalid clockTimezone. + Clock::fromArray( + [ + 'id' => 69, + 'type' => CLOCK, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'clockType' => 'digital', + 'clockFormat' => 'time', + 'clockTimezone' => 'Europe/Tokyo', + 'showClockTimezone' => false, + 'color' => 'white', + ] + ); + + // Missing clockTimezone. + Clock::fromArray( + [ + 'id' => 69, + 'type' => CLOCK, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'clockType' => 'digital', + 'clockFormat' => 'time', + 'showClockTimezone' => false, + 'color' => 'white', + ] + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"clockFormat":"time","clockTimezone":"Europe\/Madrid","clockTimezoneOffset":7200,"clockType":"digital","color":"white","height":0,"id":69,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","parentId":null,"showClockTimezone":false,"type":19,"width":0,"x":-666,"y":76}', + (string) Clock::fromArray( + [ + 'id' => 69, + 'type' => CLOCK, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'clockType' => 'digital', + 'clockFormat' => 'time', + 'clockTimezone' => 'Europe/Madrid', + 'showClockTimezone' => false, + 'color' => 'white', + ] + ) + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/ColorCloudTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/ColorCloudTest.php new file mode 100644 index 0000000000..3dbb8abe9a --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/ColorCloudTest.php @@ -0,0 +1,253 @@ +assertInstanceOf( + ColorCloud::class, + ColorCloud::fromArray( + [ + 'id' => 345, + 'type' => COLOR_CLOUD, + 'label' => null, + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'defaultColor' => '#FFF', + 'colorRanges' => [], + ] + ) + ); + + $this->assertInstanceOf( + ColorCloud::class, + ColorCloud::fromArray( + [ + 'id' => 1000, + 'type' => COLOR_CLOUD, + 'width' => 100, + 'height' => 900, + 'label' => 'eyJkZWZhdWx0X2NvbG9yIjoiI0ZGRiIsImNvbG9yX3JhbmdlcyI6W3siY29sb3IiOiIjMDAwIiwiZnJvbV92YWx1ZSI6MTAuMDUsInRvX3ZhbHVlIjoxMDAuMH1dfQ==', + 'colorRanges' => [ + [ + 'color' => '#000', + 'fromValue' => 10.05, + 'toValue' => 100.0, + ], + ], + 'color' => '#000', + ] + ) + ); + + $this->assertInstanceOf( + ColorCloud::class, + ColorCloud::fromArray( + [ + 'id' => 1000, + 'type' => COLOR_CLOUD, + 'width' => 100, + 'height' => 900, + 'label' => 'eyJkZWZhdWx0X2NvbG9yIjoiI0ZGRiIsImNvbG9yX3JhbmdlcyI6W3siY29sb3IiOiIjMDAwIiwiZnJvbV92YWx1ZSI6MTAuMDUsInRvX3ZhbHVlIjoxMDAuMH1dfQ==', + ] + ) + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"color":"#000","colorRanges":[{"color":"#000","fromValue":10.05,"toValue":100}],"defaultColor":"#FFF","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"type":20,"width":0,"x":-666,"y":76}', + (string) ColorCloud::fromArray( + [ + 'id' => 7, + 'type' => COLOR_CLOUD, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'defaultColor' => '#FFF', + 'colorRanges' => [ + [ + 'color' => '#000', + 'fromValue' => 10.05, + 'toValue' => 100.0, + ], + ], + 'color' => '#000', + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"color":null,"colorRanges":[],"defaultColor":"#FFF","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"type":20,"width":0,"x":-666,"y":76}', + (string) ColorCloud::fromArray( + [ + 'id' => 7, + 'type' => COLOR_CLOUD, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'defaultColor' => '#FFF', + 'colorRanges' => [], + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"color":"#000","colorRanges":[{"color":"#000","fromValue":10.05,"toValue":100}],"defaultColor":"#FFF","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":3,"linkedLayoutId":2,"linkedLayoutStatusType":"default","metaconsoleId":5,"moduleId":null,"moduleName":null,"parentId":null,"type":20,"width":0,"x":-666,"y":76}', + (string) ColorCloud::fromArray( + [ + 'id' => 7, + 'type' => COLOR_CLOUD, + 'label' => 'eyJkZWZhdWx0X2NvbG9yIjoiI0ZGRiIsImNvbG9yX3JhbmdlcyI6W3siY29sb3IiOiIjMDAwIiwiZnJvbV92YWx1ZSI6MTAuMDUsInRvX3ZhbHVlIjoxMDAuMH1dfQ==', + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'color' => '#000', + 'id_metaconsole' => 5, + 'linked_layout_node_id' => 3, + 'linkedLayoutId' => 2, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"color":"#000","colorRanges":[{"color":"#000","fromValue":10.05,"toValue":100}],"defaultColor":"#FFF","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":1,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"type":20,"width":0,"x":-666,"y":76}', + (string) ColorCloud::fromArray( + [ + 'id' => 7, + 'type' => COLOR_CLOUD, + 'label' => 'eyJkZWZhdWx0X2NvbG9yIjoiI0ZGRiIsImNvbG9yX3JhbmdlcyI6W3siY29sb3IiOiIjMDAwIiwiZnJvbV92YWx1ZSI6MTAuMDUsInRvX3ZhbHVlIjoxMDAuMH1dfQ==', + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'defaultColor' => '#FFF', + 'color' => '#000', + 'id_layout_linked' => 1, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"color":"#000","colorRanges":[{"color":"#000","fromValue":10.05,"toValue":100}],"defaultColor":"#FFF","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":2,"linkedLayoutStatusType":"service","linkedLayoutStatusTypeCriticalThreshold":80,"linkedLayoutStatusTypeWarningThreshold":50,"moduleId":null,"moduleName":null,"parentId":null,"type":20,"width":0,"x":-666,"y":76}', + (string) ColorCloud::fromArray( + [ + 'id' => 7, + 'type' => COLOR_CLOUD, + 'label' => 'eyJkZWZhdWx0X2NvbG9yIjoiI0ZGRiIsImNvbG9yX3JhbmdlcyI6W3siY29sb3IiOiIjMDAwIiwiZnJvbV92YWx1ZSI6MTAuMDUsInRvX3ZhbHVlIjoxMDAuMH1dfQ==', + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'colorRanges' => [ + [ + 'color' => '#000', + 'fromValue' => 10.05, + 'toValue' => 100.0, + ], + ], + 'color' => '#000', + 'linkedLayoutId' => 2, + 'linked_layout_status_type' => 'service', + 'linkedLayoutStatusTypeWarningThreshold' => 50, + 'linked_layout_status_as_service_critical' => 80, + ] + ) + ); + } + + + /** + * Test if the instance is not created when using a invalid dynamic data. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidDynamicData(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid dynamic data. + ColorCloud::fromArray( + [ + 'id' => 3, + 'type' => COLOR_CLOUD, + 'label' => null, + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '330', + 'height' => '0', + 'x' => 511, + 'y' => 76, + ] + ); + // Missing dynamic data. + ColorCloud::fromArray( + [ + 'id' => 3, + 'type' => COLOR_CLOUD, + 'label' => null, + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '330', + 'height' => '0', + 'x' => 511, + 'y' => 76, + ] + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/DonutGraphTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/DonutGraphTest.php new file mode 100644 index 0000000000..e9c0367151 --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/DonutGraphTest.php @@ -0,0 +1,103 @@ +assertInstanceOf( + DonutGraph::class, + DonutGraph::fromArray( + [ + 'id' => 3, + 'type' => DONUT_GRAPH, + 'width' => '600', + 'height' => '500', + 'legendBackgroundColor' => '#33CCFF', + 'html' => '

      Foo

      ', + ] + ) + ); + + $this->assertInstanceOf( + DonutGraph::class, + DonutGraph::fromArray( + [ + 'id' => 14, + 'type' => DONUT_GRAPH, + 'width' => '600', + 'height' => '500', + 'border_color' => '#000000', + 'encodedHtml' => 'PGgxPkZvbzwvaDE+', + ] + ) + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"encodedHtml":"PGgxPkZvbzwvaDE+","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","legendBackgroundColor":"#33CCFF","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"type":17,"width":0,"x":-666,"y":76}', + (string) DonutGraph::fromArray( + [ + 'id' => 7, + 'type' => DONUT_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'border_color' => '#33CCFF', + 'html' => '

      Foo

      ', + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"encodedHtml":"PGgxPkZvbzwvaDE+","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"left","legendBackgroundColor":"#000000","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"type":17,"width":0,"x":-666,"y":76}', + (string) DonutGraph::fromArray( + [ + 'id' => 7, + 'type' => DONUT_GRAPH, + 'label' => null, + 'labelPosition' => 'left', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'legendBackgroundColor' => '#000000', + 'encodedHtml' => 'PGgxPkZvbzwvaDE+', + ] + ) + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/EventsHistoryTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/EventsHistoryTest.php new file mode 100644 index 0000000000..3bd8e65949 --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/EventsHistoryTest.php @@ -0,0 +1,176 @@ +assertInstanceOf( + EventsHistory::class, + EventsHistory::fromArray( + [ + 'id' => 3, + 'type' => AUTO_SLA_GRAPH, + 'width' => '600', + 'height' => '500', + 'maxTime' => null, + 'html' => '

      Foo

      ', + ] + ) + ); + + $this->assertInstanceOf( + EventsHistory::class, + EventsHistory::fromArray( + [ + 'id' => 14, + 'type' => AUTO_SLA_GRAPH, + 'width' => '600', + 'height' => '500', + 'maxTime' => 12800, + 'encodedHtml' => 'PGgxPkZvbzwvaDE+', + ] + ) + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"encodedHtml":"PGgxPkZvbzwvaDE+","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","maxTime":null,"moduleId":null,"moduleName":null,"parentId":null,"type":14,"width":0,"x":-666,"y":76}', + (string) EventsHistory::fromArray( + [ + 'id' => 7, + 'type' => AUTO_SLA_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'maxTime' => null, + 'html' => '

      Foo

      ', + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"encodedHtml":"PGgxPkZvbzwvaDE+","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","maxTime":12800,"moduleId":null,"moduleName":null,"parentId":null,"type":14,"width":0,"x":-666,"y":76}', + (string) EventsHistory::fromArray( + [ + 'id' => 7, + 'type' => AUTO_SLA_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'maxTime' => 12800, + 'encodedHtml' => 'PGgxPkZvbzwvaDE+', + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"encodedHtml":"PGgxPkZvbzwvaDE+","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":1,"linkedLayoutStatusType":"default","maxTime":null,"moduleId":null,"moduleName":null,"parentId":null,"type":14,"width":0,"x":-666,"y":76}', + (string) EventsHistory::fromArray( + [ + 'id' => 7, + 'type' => AUTO_SLA_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'maxTime' => null, + 'encodedHtml' => 'PGgxPkZvbzwvaDE+', + 'id_layout_linked' => 1, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"encodedHtml":"PGgxPkZvbzwvaDE+","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":3,"linkedLayoutId":2,"linkedLayoutStatusType":"default","maxTime":12800,"metaconsoleId":5,"moduleId":null,"moduleName":null,"parentId":null,"type":14,"width":0,"x":-666,"y":76}', + (string) EventsHistory::fromArray( + [ + 'id' => 7, + 'type' => AUTO_SLA_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'maxTime' => 12800, + 'encodedHtml' => 'PGgxPkZvbzwvaDE+', + 'id_metaconsole' => 5, + 'linked_layout_node_id' => 3, + 'linkedLayoutId' => 2, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":21,"agentName":null,"encodedHtml":"PGgxPkZvbzwvaDE+","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":15,"linkedLayoutId":3,"linkedLayoutStatusType":"default","maxTime":12800,"metaconsoleId":2,"moduleId":385,"moduleName":"module_test","parentId":null,"type":14,"width":0,"x":-666,"y":76}', + (string) EventsHistory::fromArray( + [ + 'id' => 7, + 'type' => AUTO_SLA_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'maxTime' => 12800, + 'encodedHtml' => 'PGgxPkZvbzwvaDE+', + 'id_metaconsole' => 2, + 'linked_layout_node_id' => 15, + 'linkedLayoutId' => 3, + 'agentId' => 21, + 'moduleId' => 385, + 'moduleName' => 'module_test', + ] + ) + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/GroupTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/GroupTest.php new file mode 100644 index 0000000000..00e3a90620 --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/GroupTest.php @@ -0,0 +1,279 @@ +assertInstanceOf( + Group::class, + Group::fromArray( + [ + 'id' => 13, + 'type' => GROUP_ITEM, + 'width' => '600', + 'height' => '500', + 'imageSrc' => 'image.jpg', + 'groupId' => 12, + 'statusImageSrc' => 'image.bad.jpg', + ] + ) + ); + + $this->assertInstanceOf( + Group::class, + Group::fromArray( + [ + 'id' => 1004, + 'type' => GROUP_ITEM, + 'width' => '600', + 'height' => '500', + 'image' => 'test_image.png', + 'id_group' => 0, + 'statusImageSrc' => 'test_image.bad.jpg', + ] + ) + ); + } + + + /** + * Test if the instance is not created when using a invalid image src. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidImageSrc(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid imageSrc. + Group::fromArray( + [ + 'id' => 7, + 'type' => GROUP_ITEM, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => '', + 'groupId' => 0, + ] + ); + // Missing imageSrc. + Group::fromArray( + [ + 'id' => 7, + 'type' => GROUP_ITEM, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'id_group' => 11, + ] + ); + } + + + /** + * Test if the instance is not created when using a invalid group Id. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidGroupId(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid groupId. + Group::fromArray( + [ + 'id' => 7, + 'type' => GROUP_ITEM, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'test.jpg', + 'groupId' => 'bar', + 'statusImageSrc' => 'image.bad.jpg', + ] + ); + // Missing groupId. + Group::fromArray( + [ + 'id' => 7, + 'type' => GROUP_ITEM, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'test.jpg', + 'statusImageSrc' => 'image.bad.jpg', + ] + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"groupId":12,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","parentId":null,"statusImageSrc":"image.bad.jpg","type":11,"width":0,"x":-666,"y":76}', + (string) Group::fromArray( + [ + 'id' => 7, + 'type' => GROUP_ITEM, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + 'groupId' => 12, + 'statusImageSrc' => 'image.bad.jpg', + ] + ) + ); + + // With a linked layout. + $this->assertEquals( + '{"aclGroupId":null,"groupId":12,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":1,"linkedLayoutStatusType":"default","parentId":null,"statusImageSrc":"image.bad.jpg","type":11,"width":0,"x":-666,"y":76}', + (string) Group::fromArray( + [ + 'id' => 7, + 'type' => GROUP_ITEM, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + 'groupId' => 12, + 'statusImageSrc' => 'image.bad.jpg', + 'id_layout_linked' => 1, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"groupId":12,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":3,"linkedLayoutId":2,"linkedLayoutStatusType":"default","metaconsoleId":5,"parentId":null,"statusImageSrc":"image.bad.jpg","type":11,"width":0,"x":-666,"y":76}', + (string) Group::fromArray( + [ + 'id' => 7, + 'type' => GROUP_ITEM, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + 'groupId' => 12, + 'statusImageSrc' => 'image.bad.jpg', + 'id_metaconsole' => 5, + 'linked_layout_node_id' => 3, + 'linkedLayoutId' => 2, + ] + ) + ); + $this->assertEquals( + '{"aclGroupId":null,"groupId":12,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":3,"linkedLayoutId":2,"linkedLayoutStatusType":"weight","linkedLayoutStatusTypeWeight":80,"metaconsoleId":5,"parentId":null,"statusImageSrc":"image.bad.jpg","type":11,"width":0,"x":-666,"y":76}', + (string) Group::fromArray( + [ + 'id' => 7, + 'type' => GROUP_ITEM, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + 'groupId' => 12, + 'statusImageSrc' => 'image.bad.jpg', + 'id_metaconsole' => 5, + 'linked_layout_node_id' => 3, + 'linkedLayoutId' => 2, + 'linkedLayoutStatusType' => 'weight', + 'linkedLayoutStatusTypeWeight' => 80, + ] + ) + ); + $this->assertEquals( + '{"aclGroupId":null,"groupId":12,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":2,"linkedLayoutStatusType":"service","linkedLayoutStatusTypeCriticalThreshold":80,"linkedLayoutStatusTypeWarningThreshold":50,"parentId":null,"statusImageSrc":"image.bad.jpg","type":11,"width":0,"x":-666,"y":76}', + (string) Group::fromArray( + [ + 'id' => 7, + 'type' => GROUP_ITEM, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + 'groupId' => 12, + 'statusImageSrc' => 'image.bad.jpg', + 'linkedLayoutId' => 2, + 'linked_layout_status_type' => 'service', + 'linkedLayoutStatusTypeWarningThreshold' => 50, + 'linked_layout_status_as_service_critical' => 80, + ] + ) + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/IconTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/IconTest.php new file mode 100644 index 0000000000..44fa077959 --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/IconTest.php @@ -0,0 +1,207 @@ +assertInstanceOf( + Icon::class, + Icon::fromArray( + [ + 'id' => 69, + 'type' => ICON, + 'width' => '0', + 'height' => '0', + 'imageSrc' => 'image.jpg', + ] + ) + ); + } + + + /** + * Test if the instance is not created when using a invalid image src. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidImageSrc(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid imageSrc. + Icon::fromArray( + [ + 'id' => 7, + 'type' => ICON, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => '', + ] + ); + // Missing imageSrc. + Icon::fromArray( + [ + 'id' => 7, + 'type' => ICON, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + ] + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","parentId":null,"type":5,"width":0,"x":-666,"y":76}', + (string) Icon::fromArray( + [ + 'id' => 7, + 'type' => ICON, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + ] + ) + ); + + // With a linked layout. + $this->assertEquals( + '{"aclGroupId":null,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":1,"linkedLayoutStatusType":"default","parentId":null,"type":5,"width":0,"x":-666,"y":76}', + (string) Icon::fromArray( + [ + 'id' => 7, + 'type' => ICON, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + 'id_layout_linked' => 1, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":3,"linkedLayoutId":2,"linkedLayoutStatusType":"default","metaconsoleId":5,"parentId":null,"type":5,"width":0,"x":-666,"y":76}', + (string) Icon::fromArray( + [ + 'id' => 7, + 'type' => ICON, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + 'id_metaconsole' => 5, + 'linked_layout_node_id' => 3, + 'linkedLayoutId' => 2, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":3,"linkedLayoutId":2,"linkedLayoutStatusType":"weight","linkedLayoutStatusTypeWeight":80,"metaconsoleId":5,"parentId":null,"type":5,"width":0,"x":-666,"y":76}', + (string) Icon::fromArray( + [ + 'id' => 7, + 'type' => ICON, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + 'id_metaconsole' => 5, + 'linked_layout_node_id' => 3, + 'linkedLayoutId' => 2, + 'linkedLayoutStatusType' => 'weight', + 'linkedLayoutStatusTypeWeight' => 80, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":3,"linkedLayoutId":2,"linkedLayoutStatusType":"service","linkedLayoutStatusTypeCriticalThreshold":80,"linkedLayoutStatusTypeWarningThreshold":50,"metaconsoleId":5,"parentId":null,"type":5,"width":0,"x":-666,"y":76}', + (string) Icon::fromArray( + [ + 'id' => 7, + 'type' => ICON, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + 'id_metaconsole' => 5, + 'linked_layout_node_id' => 3, + 'linkedLayoutId' => 2, + 'linked_layout_status_type' => 'service', + 'linkedLayoutStatusTypeWarningThreshold' => 50, + 'linked_layout_status_as_service_critical' => 80, + ] + ) + ); + + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/LabelTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/LabelTest.php new file mode 100644 index 0000000000..2c1fd963cd --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/LabelTest.php @@ -0,0 +1,129 @@ +assertInstanceOf( + Label::class, + Label::fromArray( + [ + 'id' => 69, + 'type' => LABEL, + 'width' => '0', + 'height' => '0', + 'label' => 'Label', + ] + ) + ); + } + + + /** + * Test if the instance is not created when using a invalid label. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidLabel(): void + { + $this->expectException(InvalidArgumentException::class); + // Missing label. + Label::fromArray( + [ + 'id' => 7, + 'type' => LABEL, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + ] + ); + // Empty label. + Label::fromArray( + [ + 'id' => 7, + 'type' => LABEL, + 'label' => '', + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + ] + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":"Label","labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","parentId":null,"type":4,"width":0,"x":-666,"y":76}', + (string) Label::fromArray( + [ + 'id' => 7, + 'type' => LABEL, + 'label' => 'Label', + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + ] + ) + ); + + // With a linked layout. + $this->assertEquals( + '{"aclGroupId":null,"height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":"Label","labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":1,"linkedLayoutStatusType":"default","parentId":null,"type":4,"width":0,"x":-666,"y":76}', + (string) Label::fromArray( + [ + 'id' => 7, + 'type' => LABEL, + 'label' => 'Label', + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'id_layout_linked' => 1, + ] + ) + ); + + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/LineTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/LineTest.php new file mode 100644 index 0000000000..b70b1699a6 --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/LineTest.php @@ -0,0 +1,156 @@ +assertInstanceOf( + Line::class, + Line::fromArray( + [ + 'id' => 10, + 'type' => LINE_ITEM, + 'startX' => 50, + 'startY' => 100, + 'endX' => 0, + 'endY' => 10, + 'isOnTop' => false, + 'borderWidth' => 0, + 'borderColor' => 'white', + ] + ) + ); + + $this->assertInstanceOf( + Line::class, + Line::fromArray( + [ + 'id' => 10, + 'type' => LINE_ITEM, + 'startX' => 50, + 'endY' => 10, + 'borderColor' => 'black', + ] + ) + ); + } + + + /** + * Test if the instance is not created when using a invalid Id. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidId(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid id. + Line::fromArray( + [ + 'id' => 'foo', + 'type' => LINE_ITEM, + 'startX' => 50, + 'startY' => 100, + 'endX' => 0, + 'endY' => 10, + 'isOnTop' => false, + 'borderWidth' => 0, + 'borderColor' => 'white', + ] + ); + // Missing id. + Line::fromArray( + [ + 'type' => LINE_ITEM, + 'startX' => 50, + 'startY' => 100, + 'endX' => 0, + 'endY' => 10, + 'isOnTop' => false, + 'borderWidth' => 0, + 'borderColor' => 'white', + ] + ); + } + + + /** + * Test if the instance is not created when using a invalid type. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidtype(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid type. + Line::fromArray( + [ + 'id' => 13, + 'type' => 'test', + 'startX' => 50, + 'startY' => 100, + 'endX' => 0, + 'endY' => 10, + 'isOnTop' => false, + 'borderWidth' => 0, + 'borderColor' => 'white', + ] + ); + // Missing type. + Line::fromArray( + [ + 'id' => 13, + 'startX' => 50, + 'startY' => 100, + 'endX' => 0, + 'endY' => 10, + 'isOnTop' => true, + 'borderWidth' => 0, + 'borderColor' => 'white', + ] + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"borderColor":"white","borderWidth":0,"endX":0,"endY":10,"id":1,"isOnTop":false,"startX":50,"startY":100,"type":13}', + (string) Line::fromArray( + [ + 'id' => 1, + 'type' => LINE_ITEM, + 'startX' => 50, + 'startY' => 100, + 'endX' => 0, + 'endY' => 10, + 'isOnTop' => false, + 'borderWidth' => 0, + 'borderColor' => 'white', + ] + ) + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/PercentileTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/PercentileTest.php new file mode 100644 index 0000000000..ebe80f6b8c --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/PercentileTest.php @@ -0,0 +1,149 @@ +assertInstanceOf( + Percentile::class, + Percentile::fromArray( + [ + 'id' => 3, + 'type' => PERCENTILE_BAR, + 'width' => '600', + 'height' => '500', + 'maxTime' => null, + 'valueType' => 'value', + 'value' => '123ms', + ] + ) + ); + + $this->assertInstanceOf( + Percentile::class, + Percentile::fromArray( + [ + 'id' => 14, + 'type' => PERCENTILE_BUBBLE, + 'width' => '600', + 'height' => '500', + 'maxTime' => 12800, + 'valueType' => 'image', + 'value' => 'data:image;asdasoih==', + ] + ) + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"color":null,"height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelColor":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","maxValue":0,"minValue":null,"moduleId":null,"moduleName":null,"parentId":null,"percentileType":"progress-bar","type":3,"unit":null,"value":null,"valueType":"percent","width":0,"x":-666,"y":76}', + (string) Percentile::fromArray( + [ + 'id' => 7, + 'type' => PERCENTILE_BAR, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'maxTime' => null, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"color":null,"height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelColor":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","maxValue":0,"minValue":null,"moduleId":null,"moduleName":null,"parentId":null,"percentileType":"bubble","type":3,"unit":null,"value":null,"valueType":"percent","width":0,"x":-666,"y":76}', + (string) Percentile::fromArray( + [ + 'id' => 7, + 'type' => PERCENTILE_BUBBLE, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'maxTime' => 12800, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"color":null,"height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelColor":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","maxValue":0,"minValue":null,"moduleId":null,"moduleName":null,"parentId":null,"percentileType":"circular-progress-bar","type":3,"unit":null,"value":1,"valueType":"value","width":0,"x":-666,"y":76}', + (string) Percentile::fromArray( + [ + 'id' => 7, + 'type' => CIRCULAR_PROGRESS_BAR, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'maxTime' => 12800, + 'valueType' => 'value', + 'value' => '1', + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"color":"#FFF","height":0,"id":7,"isLinkEnabled":true,"isOnTop":false,"label":null,"labelColor":"#000","labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","maxValue":0,"minValue":null,"moduleId":null,"moduleName":null,"parentId":null,"percentileType":"circular-progress-bar","type":3,"unit":null,"value":80,"valueType":"percent","width":0,"x":-666,"y":76}', + (string) Percentile::fromArray( + [ + 'id' => 7, + 'type' => CIRCULAR_PROGRESS_BAR, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'maxTime' => 12800, + 'valueType' => 'percent', + 'value' => '80', + 'color' => '#FFF', + 'labelColor' => '#000', + ] + ) + ); + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/SimpleValueTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/SimpleValueTest.php new file mode 100644 index 0000000000..a417699fe0 --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/SimpleValueTest.php @@ -0,0 +1,148 @@ +assertInstanceOf( + SimpleValue::class, + SimpleValue::fromArray( + [ + 'id' => 3, + 'type' => SIMPLE_VALUE, + 'width' => '600', + 'height' => '500', + 'valueType' => 'string', + 'value' => 57, + 'processValue' => 'avg', + 'period' => 12800, + ] + ) + ); + + $this->assertInstanceOf( + SimpleValue::class, + SimpleValue::fromArray( + [ + 'id' => 14, + 'type' => SIMPLE_VALUE, + 'width' => '600', + 'height' => '500', + 'valueType' => 'image', + 'value' => 3598, + 'processValue' => 'max', + 'period' => 9000, + ] + ) + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"height":500,"id":3,"isLinkEnabled":false,"isOnTop":false,"label":null,"labelPosition":"down","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"period":12800,"processValue":"avg","type":2,"value":57,"valueType":"string","width":600,"x":0,"y":0}', + (string) SimpleValue::fromArray( + [ + 'id' => 3, + 'type' => SIMPLE_VALUE, + 'width' => '600', + 'height' => '500', + 'valueType' => 'string', + 'value' => 57, + 'processValue' => 'avg', + 'period' => 12800, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"height":500,"id":3,"isLinkEnabled":false,"isOnTop":false,"label":null,"labelPosition":"down","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"processValue":"none","type":2,"value":57,"valueType":"string","width":600,"x":0,"y":0}', + (string) SimpleValue::fromArray( + [ + 'id' => 3, + 'type' => SIMPLE_VALUE, + 'width' => '600', + 'height' => '500', + 'valueType' => 'string', + 'value' => 57, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"height":500,"id":3,"isLinkEnabled":false,"isOnTop":false,"label":null,"labelPosition":"down","linkedLayoutAgentId":null,"linkedLayoutId":1,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"processValue":"none","type":2,"value":57,"valueType":"string","width":600,"x":0,"y":0}', + (string) SimpleValue::fromArray( + [ + 'id' => 3, + 'type' => SIMPLE_VALUE, + 'width' => '600', + 'height' => '500', + 'valueType' => 'string', + 'value' => 57, + 'id_layout_linked' => 1, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"height":500,"id":3,"isLinkEnabled":false,"isOnTop":false,"label":null,"labelPosition":"down","linkedLayoutAgentId":3,"linkedLayoutId":2,"linkedLayoutStatusType":"default","metaconsoleId":5,"moduleId":null,"moduleName":null,"parentId":null,"processValue":"none","type":2,"value":57,"valueType":"string","width":600,"x":0,"y":0}', + (string) SimpleValue::fromArray( + [ + 'id' => 3, + 'type' => SIMPLE_VALUE, + 'width' => '600', + 'height' => '500', + 'valueType' => 'string', + 'value' => 57, + 'id_metaconsole' => 5, + 'linked_layout_node_id' => 3, + 'linkedLayoutId' => 2, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":21,"agentName":null,"height":500,"id":3,"isLinkEnabled":false,"isOnTop":false,"label":null,"labelPosition":"down","linkedLayoutAgentId":15,"linkedLayoutId":3,"linkedLayoutStatusType":"default","metaconsoleId":2,"moduleId":385,"moduleName":"module_test","parentId":null,"processValue":"none","type":2,"value":57,"valueType":"string","width":600,"x":0,"y":0}', + (string) SimpleValue::fromArray( + [ + 'id' => 3, + 'type' => SIMPLE_VALUE, + 'width' => '600', + 'height' => '500', + 'valueType' => 'string', + 'value' => 57, + 'id_metaconsole' => 2, + 'linked_layout_node_id' => 15, + 'linkedLayoutId' => 3, + 'agentId' => 21, + 'moduleId' => 385, + 'moduleName' => 'module_test', + ] + ) + ); + + } + + +} diff --git a/pandora_console/tests/Functional/Models/VisualConsole/Items/StaticGraphTest.php b/pandora_console/tests/Functional/Models/VisualConsole/Items/StaticGraphTest.php new file mode 100644 index 0000000000..9b77fc7540 --- /dev/null +++ b/pandora_console/tests/Functional/Models/VisualConsole/Items/StaticGraphTest.php @@ -0,0 +1,224 @@ +assertInstanceOf( + StaticGraph::class, + StaticGraph::fromArray( + [ + 'id' => 345, + 'type' => STATIC_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'aaaaa', + 'showLastValueTooltip' => 'enabled', + ] + ) + ); + + $this->assertInstanceOf( + StaticGraph::class, + StaticGraph::fromArray( + [ + 'id' => 1000, + 'type' => STATIC_GRAPH, + 'width' => 100, + 'height' => 900, + 'image' => 'test.jpg', + 'show_last_value' => 2, + ] + ) + ); + } + + + /** + * Test if the model has a valid JSON representation. + * + * @return void + */ + public function testContainerIsRepresentedAsJson(): void + { + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"showLastValueTooltip":"default","statusImageSrc":null,"type":0,"width":0,"x":-666,"y":76}', + (string) StaticGraph::fromArray( + [ + 'id' => 7, + 'type' => STATIC_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":null,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"showLastValueTooltip":"disabled","statusImageSrc":null,"type":0,"width":0,"x":-666,"y":76}', + (string) StaticGraph::fromArray( + [ + 'id' => 7, + 'type' => STATIC_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'image' => 'image.jpg', + 'showLastValueTooltip' => 'disabled', + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":3,"linkedLayoutId":2,"linkedLayoutStatusType":"default","metaconsoleId":5,"moduleId":null,"moduleName":null,"parentId":null,"showLastValueTooltip":"default","statusImageSrc":"image.bad.jpg","type":0,"width":0,"x":-666,"y":76}', + (string) StaticGraph::fromArray( + [ + 'id' => 7, + 'type' => STATIC_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'imageSrc' => 'image.jpg', + 'id_metaconsole' => 5, + 'linked_layout_node_id' => 3, + 'linkedLayoutId' => 2, + 'statusImageSrc' => 'image.bad.jpg', + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":1,"linkedLayoutStatusType":"default","moduleId":null,"moduleName":null,"parentId":null,"showLastValueTooltip":"default","statusImageSrc":null,"type":0,"width":0,"x":-666,"y":76}', + (string) StaticGraph::fromArray( + [ + 'id' => 7, + 'type' => STATIC_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'image' => 'image.jpg', + 'id_layout_linked' => 1, + ] + ) + ); + + $this->assertEquals( + '{"aclGroupId":null,"agentId":null,"agentName":null,"height":0,"id":7,"imageSrc":"image.jpg","isLinkEnabled":true,"isOnTop":false,"label":null,"labelPosition":"up","linkedLayoutAgentId":null,"linkedLayoutId":2,"linkedLayoutStatusType":"service","linkedLayoutStatusTypeCriticalThreshold":80,"linkedLayoutStatusTypeWarningThreshold":50,"moduleId":null,"moduleName":null,"parentId":null,"showLastValueTooltip":"default","statusImageSrc":"image.bad.jpg","type":0,"width":0,"x":-666,"y":76}', + (string) StaticGraph::fromArray( + [ + 'id' => 7, + 'type' => STATIC_GRAPH, + 'label' => null, + 'labelPosition' => 'up', + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '0', + 'height' => '0', + 'x' => -666, + 'y' => 76, + 'image' => 'image.jpg', + 'linkedLayoutId' => 2, + 'linked_layout_status_type' => 'service', + 'linkedLayoutStatusTypeWarningThreshold' => 50, + 'linked_layout_status_as_service_critical' => 80, + 'statusImageSrc' => 'image.bad.jpg', + ] + ) + ); + } + + + /** + * Test if the instance is not created when using a invalid image src. + * + * @return void + */ + public function testCannotBeCreatedWithInvalidImageSrc(): void + { + $this->expectException(InvalidArgumentException::class); + // Invalid imageSrc. + StaticGraph::fromArray( + [ + 'id' => 3, + 'type' => STATIC_GRAPH, + 'label' => null, + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '330', + 'height' => '0', + 'x' => 511, + 'y' => 76, + 'imageSrc' => 45, + 'showLastValueTooltip' => 'disabled', + ] + ); + + // Missing imageSrc. + StaticGraph::fromArray( + [ + 'id' => 3, + 'type' => STATIC_GRAPH, + 'label' => null, + 'isLinkEnabled' => true, + 'isOnTop' => false, + 'parentId' => null, + 'width' => '330', + 'height' => '0', + 'x' => 511, + 'y' => 76, + 'showLastValueTooltip' => 'enabled', + ] + ); + } + + +} diff --git a/pandora_console/tests/bootstrap.php b/pandora_console/tests/bootstrap.php new file mode 100644 index 0000000000..c2d6c31bf2 --- /dev/null +++ b/pandora_console/tests/bootstrap.php @@ -0,0 +1,4 @@ +apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** diff --git a/pandora_console/vendor/composer/autoload_psr4.php b/pandora_console/vendor/composer/autoload_psr4.php index cd3de7c147..57404185e1 100644 --- a/pandora_console/vendor/composer/autoload_psr4.php +++ b/pandora_console/vendor/composer/autoload_psr4.php @@ -6,8 +6,11 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'Tests\\' => array($baseDir . '/tests'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Mpdf\\' => array($vendorDir . '/mpdf/mpdf/src'), + 'Models\\' => array($baseDir . '/include/rest-api/models'), + 'Enterprise\\Models\\' => array($baseDir . '/enterprise/include/rest-api/models'), 'Egulias\\EmailValidator\\' => array($vendorDir . '/egulias/email-validator/EmailValidator'), 'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'), ); diff --git a/pandora_console/vendor/composer/autoload_static.php b/pandora_console/vendor/composer/autoload_static.php index 2e8ac5a72e..f6d8bc0456 100644 --- a/pandora_console/vendor/composer/autoload_static.php +++ b/pandora_console/vendor/composer/autoload_static.php @@ -12,6 +12,10 @@ class ComposerStaticInitfdecadadce22e6dde51e9535fe4ad7aa ); public static $prefixLengthsPsr4 = array ( + 'T' => + array ( + 'Tests\\' => 6, + ), 'P' => array ( 'Psr\\Log\\' => 8, @@ -19,9 +23,11 @@ class ComposerStaticInitfdecadadce22e6dde51e9535fe4ad7aa 'M' => array ( 'Mpdf\\' => 5, + 'Models\\' => 7, ), 'E' => array ( + 'Enterprise\\Models\\' => 18, 'Egulias\\EmailValidator\\' => 23, ), 'D' => @@ -31,6 +37,10 @@ class ComposerStaticInitfdecadadce22e6dde51e9535fe4ad7aa ); public static $prefixDirsPsr4 = array ( + 'Tests\\' => + array ( + 0 => __DIR__ . '/../..' . '/tests', + ), 'Psr\\Log\\' => array ( 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', @@ -39,6 +49,14 @@ class ComposerStaticInitfdecadadce22e6dde51e9535fe4ad7aa array ( 0 => __DIR__ . '/..' . '/mpdf/mpdf/src', ), + 'Models\\' => + array ( + 0 => __DIR__ . '/../..' . '/include/rest-api/models', + ), + 'Enterprise\\Models\\' => + array ( + 0 => __DIR__ . '/../..' . '/enterprise/include/rest-api/models', + ), 'Egulias\\EmailValidator\\' => array ( 0 => __DIR__ . '/..' . '/egulias/email-validator/EmailValidator', diff --git a/pandora_server/DEBIAN/control b/pandora_server/DEBIAN/control index ae71ae840a..8759fe7140 100644 --- a/pandora_server/DEBIAN/control +++ b/pandora_server/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-server -Version: 7.0NG.734-190425 +Version: 7.0NG.734-190513 Architecture: all Priority: optional Section: admin diff --git a/pandora_server/DEBIAN/make_deb_package.sh b/pandora_server/DEBIAN/make_deb_package.sh index 46dfa57d41..35d23e5ea8 100644 --- a/pandora_server/DEBIAN/make_deb_package.sh +++ b/pandora_server/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.734-190425" +pandora_version="7.0NG.734-190513" package_cpan=0 package_pandora=1 diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 5f6908de2d..d2a956b578 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -45,7 +45,7 @@ our @EXPORT = qw( # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.734"; -my $pandora_build = "190425"; +my $pandora_build = "190513"; our $VERSION = $pandora_version." ".$pandora_build; # Setup hash diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index 29d3f14f62..296be928a4 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -391,7 +391,11 @@ sub pandora_generate_alerts ($$$$$$$$;$$$) { } # Get enabled alerts associated with this module - my $alert_type_filter = defined ($alert_type) ? " AND type = '$alert_type'" : ''; + my $alert_type_filter = ''; + if (defined($alert_type)) { + # not_normal includes unknown! + $alert_type_filter = $alert_type eq 'unknown' ? " AND (type = 'unknown' OR type = 'not_normal')" : " AND type = '$alert_type'"; + } my @alerts = get_db_rows ($dbh, ' SELECT talert_template_modules.id as id_template_module, talert_template_modules.*, talert_templates.* @@ -566,6 +570,7 @@ sub pandora_evaluate_alert ($$$$$$$;$$$) { return $status if ($last_status != 1 && $alert->{'type'} eq 'critical'); return $status if ($last_status != 2 && $alert->{'type'} eq 'warning'); return $status if ($last_status != 3 && $alert->{'type'} eq 'unknown'); + return $status if ($last_status == 0 && $alert->{'type'} eq 'not_normal'); } # Event alert else { @@ -4238,7 +4243,7 @@ sub get_module_status ($$$) { $critical_str = (defined ($critical_str) && valid_regex ($critical_str) == 1) ? safe_output($critical_str) : ''; $warning_str = (defined ($warning_str) && valid_regex ($warning_str) == 1) ? safe_output($warning_str) : ''; - if ($module_type =~ m/_proc$/ && ($critical_min eq $critical_max)) { + if (($module_type =~ m/_proc$/ || $module_type =~ /web_analysis/) && ($critical_min eq $critical_max)) { ($critical_min, $critical_max) = (0, 1); } elsif ($module_type =~ m/keep_alive/ && ($critical_min eq $critical_max)) { diff --git a/pandora_server/lib/PandoraFMS/PluginTools.pm b/pandora_server/lib/PandoraFMS/PluginTools.pm index aaf8d672b0..925f5b059a 100644 --- a/pandora_server/lib/PandoraFMS/PluginTools.pm +++ b/pandora_server/lib/PandoraFMS/PluginTools.pm @@ -32,7 +32,7 @@ our @ISA = qw(Exporter); # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.734"; -my $pandora_build = "190425"; +my $pandora_build = "190513"; our $VERSION = $pandora_version." ".$pandora_build; our %EXPORT_TAGS = ( 'all' => [ qw() ] ); diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec index 869839e7a5..b64de7a201 100644 --- a/pandora_server/pandora_server.redhat.spec +++ b/pandora_server/pandora_server.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_server %define version 7.0NG.734 -%define release 190425 +%define release 190513 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec index 98759c168c..b9722e6f4d 100644 --- a/pandora_server/pandora_server.spec +++ b/pandora_server/pandora_server.spec @@ -3,7 +3,7 @@ # %define name pandorafms_server %define version 7.0NG.734 -%define release 190425 +%define release 190513 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer index af1ef4aecf..92bec4f982 100755 --- a/pandora_server/pandora_server_installer +++ b/pandora_server/pandora_server_installer @@ -9,7 +9,7 @@ # ********************************************************************** PI_VERSION="7.0NG.734" -PI_BUILD="190425" +PI_BUILD="190513" MODE=$1 if [ $# -gt 1 ]; then diff --git a/pandora_server/util/pandora_db.pl b/pandora_server/util/pandora_db.pl index e1a8ec5590..48edb7c593 100644 --- a/pandora_server/util/pandora_db.pl +++ b/pandora_server/util/pandora_db.pl @@ -34,7 +34,7 @@ use PandoraFMS::Config; use PandoraFMS::DB; # version: define current version -my $version = "7.0NG.734 PS190425"; +my $version = "7.0NG.734 PS190513"; # Pandora server configuration my %conf; diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl index 42d1496bbc..76ef33ff9a 100644 --- a/pandora_server/util/pandora_manage.pl +++ b/pandora_server/util/pandora_manage.pl @@ -36,7 +36,7 @@ use Encode::Locale; Encode::Locale::decode_argv; # version: define current version -my $version = "7.0NG.734 PS190425"; +my $version = "7.0NG.734 PS190513"; # save program name for logging my $progname = basename($0); @@ -155,6 +155,7 @@ sub help_screen{ help_screen_line('--update_module', ' ', 'Update a module field'); help_screen_line('--get_agents_module_current_data', '', "Get the agent and current data \n\t of all the modules with a given name"); help_screen_line('--create_network_module_from_component', ' ', "Create a new network \n\t module from a network component"); + help_screen_line('--create_network_component', " \n\t [ \n\t \n\t \n\t \n\t \n\t \n\t ]", "Create a new network component"); help_screen_line('--create_synthetic', " ,,|, \n\t [ , | ,, ]", "Create a new Synthetic module"); print "\nALERTS:\n\n" unless $param ne ''; help_screen_line('--create_template_module', ' ', 'Add alert template to module'); @@ -1685,6 +1686,23 @@ sub cli_create_network_module_from_component() { pandora_create_module_from_network_component ($conf, $component, $agent_id, $dbh); } +############################################################################## +# Create a network component. +# Related option: --create_network_component +############################################################################## +sub cli_create_network_component() { + my ($c_name, $c_group, $c_type) = @ARGV[2..4]; + my @todo = @ARGV[5..20]; + my $other = join('|', @todo); + my @todo2 = @ARGV[22..26]; + my $other2 = join('|', @todo2); + + # Call the API. + my $result = api_call( $conf, 'set', 'new_network_component', $c_name, undef, "$c_type|$other|$c_group|$other2"); + + print "$result \n\n "; +} + ############################################################################## # Create netflow filter # Related option: --create_netflow_filter @@ -6204,6 +6222,10 @@ sub pandora_manage_main ($$$) { param_check($ltotal, 2); cli_create_network_module_from_component(); } + elsif ($param eq '--create_network_component') { + param_check($ltotal, 24, 21); + cli_create_network_component(); + } elsif ($param eq '--create_netflow_filter') { param_check($ltotal, 5); cli_create_netflow_filter(); diff --git a/visual_console_client/.eslintrc b/visual_console_client/.eslintrc new file mode 100644 index 0000000000..af67551834 --- /dev/null +++ b/visual_console_client/.eslintrc @@ -0,0 +1,19 @@ +{ + "env": { + "browser": true, + "node": true, + "jest": true + }, + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint", "prettier"], + "extends": [ + "eslint:recommended", + "plugin:prettier/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "no-console": "off", + "@typescript-eslint/indent": "off", + "@typescript-eslint/explicit-function-return-type": "off" + } +} diff --git a/visual_console_client/.gitignore b/visual_console_client/.gitignore new file mode 100644 index 0000000000..46091fbe36 --- /dev/null +++ b/visual_console_client/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build +/dist + +# editor +# .vscode + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/visual_console_client/.vscode/launch.json b/visual_console_client/.vscode/launch.json new file mode 100644 index 0000000000..115b2f51b6 --- /dev/null +++ b/visual_console_client/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense para saber los atributos posibles. + // Mantenga el puntero para ver las descripciones de los existentes atributos + // Para más información, visite: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Debug", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}" + } + ] +} diff --git a/visual_console_client/.vscode/settings.json b/visual_console_client/.vscode/settings.json new file mode 100644 index 0000000000..024b36878e --- /dev/null +++ b/visual_console_client/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib", + "editor.formatOnSave": true, + "eslint.validate": [ + "javascript", + "javascriptreact", + "typescript", + "typescriptreact" + ] +} diff --git a/visual_console_client/README.md b/visual_console_client/README.md new file mode 100644 index 0000000000..b480fac939 --- /dev/null +++ b/visual_console_client/README.md @@ -0,0 +1 @@ +# Visual Console Client diff --git a/visual_console_client/__mocks__/fileMock.js b/visual_console_client/__mocks__/fileMock.js new file mode 100644 index 0000000000..0a445d0600 --- /dev/null +++ b/visual_console_client/__mocks__/fileMock.js @@ -0,0 +1 @@ +module.exports = "test-file-stub"; diff --git a/visual_console_client/__mocks__/styleMock.js b/visual_console_client/__mocks__/styleMock.js new file mode 100644 index 0000000000..f053ebf797 --- /dev/null +++ b/visual_console_client/__mocks__/styleMock.js @@ -0,0 +1 @@ +module.exports = {}; diff --git a/visual_console_client/jest.config.js b/visual_console_client/jest.config.js new file mode 100644 index 0000000000..ec2b954ec2 --- /dev/null +++ b/visual_console_client/jest.config.js @@ -0,0 +1,14 @@ +module.exports = { + roots: ["/src"], + transform: { + "^.+\\.tsx?$": "ts-jest" + }, + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + // This configuration is used to mock the css and file imports used by Webpack. + // https://jestjs.io/docs/en/webpack.html + moduleNameMapper: { + "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": + "/__mocks__/fileMock.js", + "\\.(css|less)$": "/__mocks__/styleMock.js" + } +}; diff --git a/visual_console_client/package-lock.json b/visual_console_client/package-lock.json new file mode 100644 index 0000000000..c5a4da6f7a --- /dev/null +++ b/visual_console_client/package-lock.json @@ -0,0 +1,7957 @@ +{ + "name": "pandora-fms-visual-console", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.3.tgz", + "integrity": "sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.0", + "@babel/helpers": "^7.4.3", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "requires": { + "minimist": "^1.2.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "@babel/generator": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz", + "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", + "requires": { + "@babel/types": "^7.4.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==" + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.0.tgz", + "integrity": "sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw==", + "requires": { + "@babel/types": "^7.4.0" + } + }, + "@babel/helpers": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.3.tgz", + "integrity": "sha512-BMh7X0oZqb36CfyhvtbSmcWc3GXocfxv3yNsAEuM0l+fAqSO22rQrUpijr3oE/10jCTrB6/0b9kzmG4VetCj8Q==", + "requires": { + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz", + "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==" + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/template": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.0.tgz", + "integrity": "sha512-SOWwxxClTTh5NdbbYZ0BmaBVzxzTh2tO/TeLTbF6MO6EzVhHTnff8CdBXx3mEtazFBoysmEM6GU/wF+SuSx4Fw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.0", + "@babel/types": "^7.4.0" + } + }, + "@babel/traverse": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.3.tgz", + "integrity": "sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.0", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/types": "^7.4.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "@babel/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", + "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@jest/console": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz", + "integrity": "sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg==", + "requires": { + "@jest/source-map": "^24.3.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + } + }, + "@jest/core": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.7.1.tgz", + "integrity": "sha512-ivlZ8HX/FOASfHcb5DJpSPFps8ydfUYzLZfgFFqjkLijYysnIEOieg72YRhO4ZUB32xu40hsSMmaw+IGYeKONA==", + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.7.0", + "jest-config": "^24.7.1", + "jest-haste-map": "^24.7.1", + "jest-message-util": "^24.7.1", + "jest-regex-util": "^24.3.0", + "jest-resolve-dependencies": "^24.7.1", + "jest-runner": "^24.7.1", + "jest-runtime": "^24.7.1", + "jest-snapshot": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", + "jest-watcher": "^24.7.1", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "@jest/environment": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.7.1.tgz", + "integrity": "sha512-wmcTTYc4/KqA+U5h1zQd5FXXynfa7VGP2NfF+c6QeGJ7c+2nStgh65RQWNX62SC716dTtqheTRrZl0j+54oGHw==", + "requires": { + "@jest/fake-timers": "^24.7.1", + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "jest-mock": "^24.7.0" + } + }, + "@jest/fake-timers": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.7.1.tgz", + "integrity": "sha512-4vSQJDKfR2jScOe12L9282uiwuwQv9Lk7mgrCSZHA9evB9efB/qx8i0KJxsAKtp8fgJYBJdYY7ZU6u3F4/pyjA==", + "requires": { + "@jest/types": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-mock": "^24.7.0" + } + }, + "@jest/reporters": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.7.1.tgz", + "integrity": "sha512-bO+WYNwHLNhrjB9EbPL4kX/mCCG4ZhhfWmO3m4FSpbgr7N83MFejayz30kKjgqr7smLyeaRFCBQMbXpUgnhAJw==", + "requires": { + "@jest/environment": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-api": "^2.1.1", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-source-maps": "^3.0.1", + "jest-haste-map": "^24.7.1", + "jest-resolve": "^24.7.1", + "jest-runtime": "^24.7.1", + "jest-util": "^24.7.1", + "jest-worker": "^24.6.0", + "node-notifier": "^5.2.1", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/source-map": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.3.0.tgz", + "integrity": "sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag==", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/test-result": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.7.1.tgz", + "integrity": "sha512-3U7wITxstdEc2HMfBX7Yx3JZgiNBubwDqQMh+BXmZXHa3G13YWF3p6cK+5g0hGkN3iufg/vGPl3hLxQXD74Npg==", + "requires": { + "@jest/console": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.7.1.tgz", + "integrity": "sha512-84HQkCpVZI/G1zq53gHJvSmhUer4aMYp9tTaffW28Ih5OxfCg8hGr3nTSbL1OhVDRrFZwvF+/R9gY6JRkDUpUA==", + "requires": { + "@jest/test-result": "^24.7.1", + "jest-haste-map": "^24.7.1", + "jest-runner": "^24.7.1", + "jest-runtime": "^24.7.1" + } + }, + "@jest/transform": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.7.1.tgz", + "integrity": "sha512-EsOUqP9ULuJ66IkZQhI5LufCHlTbi7hrcllRMUEV/tOgqBVQi93+9qEvkX0n8mYpVXQ8VjwmICeRgg58mrtIEw==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.7.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.7.1", + "jest-regex-util": "^24.3.0", + "jest-util": "^24.7.1", + "micromatch": "^3.1.10", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/types": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.7.0.tgz", + "integrity": "sha512-ipJUa2rFWiKoBqMKP63Myb6h9+iT3FHRTF2M8OR6irxWzItisa8i4dcSg14IbvmXUnBlHBlUQPYUHWyX3UPpYA==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/yargs": "^12.0.9" + } + }, + "@types/babel__core": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.1.tgz", + "integrity": "sha512-+hjBtgcFPYyCTo0A15+nxrCVJL7aC6Acg87TXd5OW3QhHswdrOLoles+ldL2Uk8q++7yIfl4tURtztccdeeyOw==", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.0.2.tgz", + "integrity": "sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.6.tgz", + "integrity": "sha512-XYVgHF2sQ0YblLRMLNPB3CkFMewzFmlDsH/TneZFHUXDlABQgh88uOxuez7ZcXxayLFrqLwtDH1t+FmlFwNZxw==", + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/d3-path": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.8.tgz", + "integrity": "sha512-AZGHWslq/oApTAHu9+yH/Bnk63y9oFOMROtqPAtxl5uB6qm1x2lueWdVEjsjjV3Qc2+QfuzKIwIR5MvVBakfzA==" + }, + "@types/d3-shape": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.1.tgz", + "integrity": "sha512-usqdvUvPJ7AJNwpd2drOzRKs1ELie53p2m2GnPKr076/ADM579jVTJ5dPsoZ5E/CMNWk8lvPWYQSvilpp6jjwg==", + "requires": { + "@types/d3-path": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz", + "integrity": "sha512-eAtOAFZefEnfJiRFQBGw1eYqa5GTLCZ1y86N0XSI/D6EB+E8z6VPV/UL7Gi5UEclFqoQk+6NRqEDsfmDLXn8sg==" + }, + "@types/jest": { + "version": "24.0.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.11.tgz", + "integrity": "sha512-2kLuPC5FDnWIDvaJBzsGTBQaBbnDweznicvK7UGYzlIJP4RJR2a4A/ByLUXEyEgag6jz8eHdlWExGDtH3EYUXQ==", + "requires": { + "@types/jest-diff": "*" + } + }, + "@types/jest-diff": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz", + "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==" + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==" + }, + "@types/yargs": { + "version": "12.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.12.tgz", + "integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==" + }, + "@typescript-eslint/eslint-plugin": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.6.0.tgz", + "integrity": "sha512-U224c29E2lo861TQZs6GSmyC0OYeRNg6bE9UVIiFBxN2MlA0nq2dCrgIVyyRbC05UOcrgf2Wk/CF2gGOPQKUSQ==", + "requires": { + "@typescript-eslint/parser": "1.6.0", + "@typescript-eslint/typescript-estree": "1.6.0", + "requireindex": "^1.2.0", + "tsutils": "^3.7.0" + } + }, + "@typescript-eslint/parser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.6.0.tgz", + "integrity": "sha512-VB9xmSbfafI+/kI4gUK3PfrkGmrJQfh0N4EScT1gZXSZyUxpsBirPL99EWZg9MmPG0pzq/gMtgkk7/rAHj4aQw==", + "requires": { + "@typescript-eslint/typescript-estree": "1.6.0", + "eslint-scope": "^4.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.6.0.tgz", + "integrity": "sha512-A4CanUwfaG4oXobD5y7EXbsOHjCwn8tj1RDd820etpPAjH+Icjc2K9e/DQM1Hac5zH2BSy+u6bjvvF2wwREvYA==", + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + } + }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==" + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==" + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==" + }, + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==" + }, + "acorn-globals": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + } + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==" + }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==" + }, + "ajv": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + }, + "ajv-keywords": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", + "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==" + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "requires": { + "lodash": "^4.17.11" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "awesome-typescript-loader": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz", + "integrity": "sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==", + "requires": { + "chalk": "^2.4.1", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.1.0", + "lodash": "^4.17.5", + "micromatch": "^3.1.9", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.3", + "webpack-log": "^1.2.0" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "babel-jest": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.7.1.tgz", + "integrity": "sha512-GPnLqfk8Mtt0i4OemjWkChi73A3ALs4w2/QbG64uAj8b5mmwzxc7jbJVRZt8NJkxi6FopVHog9S3xX6UJKb2qg==", + "requires": { + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.6.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.1.tgz", + "integrity": "sha512-RNNVv2lsHAXJQsEJ5jonQwrJVWK8AcZpG1oxhnjCUaAjL7xahYLANhPUZbzEQHjKy1NMYUwn+0NPKQc8iSY4xQ==", + "requires": { + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.0.0", + "test-exclude": "^5.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz", + "integrity": "sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w==", + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz", + "integrity": "sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw==", + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.6.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", + "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==" + }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==" + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", + "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cacache": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", + "requires": { + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "callsites": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", + "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==" + }, + "camelcase": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", + "integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==" + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "requires": { + "rsvp": "^4.8.4" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "chokidar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.2.tgz", + "integrity": "sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.0" + } + }, + "chownr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" + }, + "chrome-trace-event": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", + "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-webpack-plugin": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-2.0.1.tgz", + "integrity": "sha512-vway5pXGVd91bicwjaf8j188Al6VMf9R9Ekl6q0qeiaWStRsOOXuh4qtjX1UrUvmz5XevQVCdjBuzr4Tzsnpog==", + "requires": { + "del": "^4.0.0" + }, + "dependencies": { + "del": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-4.0.0.tgz", + "integrity": "sha512-/BnSJ+SuZyLu7xMn48kZY0nMXDi+5KNmR4g8n21Wivsl8+B9njV6/5kcTNE9juSprp0zRWBU28JuHUq0FqK1Nw==", + "requires": { + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.2" + } + }, + "is-path-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.0.0.tgz", + "integrity": "sha512-m5dHHzpOXEiv18JEORttBO64UgTEypx99vCxQLjbBvGhOJxnTNglYoFXxwo6AbsQb79sqqycQEHv2hWkHZAijA==" + }, + "is-path-in-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.0.0.tgz", + "integrity": "sha512-6Vz5Gc9s/sDA3JBVu0FzWufm8xaBsqy1zn8Q6gmvGP6nSDMw78aS4poBNeatWjaRpTpxxLn1WOndAiOlk+qY8A==", + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "p-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.0.0.tgz", + "integrity": "sha512-GO107XdrSUmtHxVoi60qc9tUl/KkNKm+X2CF4P9amalpGxv5YqVPJNfSb0wcA+syCopkZvYYIzW8OVTQW59x/w==" + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "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=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "compare-versions": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.4.0.tgz", + "integrity": "sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "compressible": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.16.tgz", + "integrity": "sha512-JQfEOdnI7dASwCuSPWIeVYwc/zMsu/+tRhoUvEfXz2gxOA2DNjmG5vhtFdBlhWPPGo+RdT9S3tgc/uH5qgDiiA==", + "requires": { + "mime-db": ">= 1.38.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "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", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "requires": { + "date-now": "^0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-loader": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", + "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", + "requires": { + "camelcase": "^5.2.0", + "icss-utils": "^4.1.0", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.14", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^2.0.6", + "postcss-modules-scope": "^2.1.0", + "postcss-modules-values": "^2.0.0", + "postcss-value-parser": "^3.3.0", + "schema-utils": "^1.0.0" + } + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + }, + "cssom": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", + "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==" + }, + "cssstyle": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.2.tgz", + "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", + "requires": { + "cssom": "0.3.x" + } + }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=" + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "^0.10.9" + } + }, + "d3-path": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.7.tgz", + "integrity": "sha512-q0cW1RpvA5c5ma2rch62mX8AYaiLX0+bdaSM2wxSU9tXjU4DNvkx9qiUvjkuWCj3p22UO/hlPivujqMiR9PDzA==" + }, + "d3-shape": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.5.tgz", + "integrity": "sha512-VKazVR3phgD+MUCldapHD7P9kcrvPcexeX/PkMJmkUov4JM8IxsSg1DvbYoYich9AtdTsa5nNk2++ImPiDiSxg==", + "requires": { + "d3-path": "1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "requires": { + "strip-bom": "^3.0.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "del": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.0.tgz", + "integrity": "sha512-C4kvKNlYrwXhKxz97BuohF8YoGgQ23Xm9lvoHmgT7JaPGprSEjk3+XFled74Yt/x0ZABUHg2D67covzAPUKx5Q==", + "requires": { + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==" + }, + "diff-sequences": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.3.0.tgz", + "integrity": "sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "requires": { + "esutils": "^2.0.2" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.47", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.47.tgz", + "integrity": "sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + } + } + }, + "eslint-config-prettier": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-4.1.0.tgz", + "integrity": "sha512-zILwX9/Ocz4SV2vX7ox85AsrAgXV3f2o2gpIicdMIOra48WYqgUnWNH/cR/iHtmD2Vb3dLSC3LiEJnS05Gkw7w==", + "requires": { + "get-stdin": "^6.0.0" + } + }, + "eslint-plugin-prettier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz", + "integrity": "sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ==", + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==" + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==" + }, + "events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==" + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "requires": { + "original": "^1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exec-sh": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", + "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==" + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "expect": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.7.1.tgz", + "integrity": "sha512-mGfvMTPduksV3xoI0xur56pQsg2vJjNf5+a+bXOjqCkiCBbmCayrBbHS/75y9K430cfqyocPr2ZjiNiRx4SRKw==", + "requires": { + "@jest/types": "^24.7.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.3.0", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-regex-util": "^24.3.0" + } + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "requires": { + "bser": "^2.0.0" + } + }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==" + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", + "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" + } + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==" + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", + "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", + "requires": { + "debug": "^3.2.6" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.2.4", + "bundled": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.3", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.2.0", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.6.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "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==" + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==" + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" + }, + "handle-thing": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", + "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==" + }, + "handlebars": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-parser-js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", + "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==" + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=" + }, + "icss-utils": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.0.tgz", + "integrity": "sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ==", + "requires": { + "postcss": "^7.0.14" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", + "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + } + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", + "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.11", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" + } + } + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "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==" + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-path-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.0.0.tgz", + "integrity": "sha512-m5dHHzpOXEiv18JEORttBO64UgTEypx99vCxQLjbBvGhOJxnTNglYoFXxwo6AbsQb79sqqycQEHv2hWkHZAijA==" + }, + "is-path-in-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.0.0.tgz", + "integrity": "sha512-6Vz5Gc9s/sDA3JBVu0FzWufm8xaBsqy1zn8Q6gmvGP6nSDMw78aS4poBNeatWjaRpTpxxLn1WOndAiOlk+qY8A==", + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul-api": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.1.tgz", + "integrity": "sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw==", + "requires": { + "async": "^2.6.1", + "compare-versions": "^3.2.1", + "fileset": "^2.0.3", + "istanbul-lib-coverage": "^2.0.3", + "istanbul-lib-hook": "^2.0.3", + "istanbul-lib-instrument": "^3.1.0", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.2", + "istanbul-reports": "^2.1.1", + "js-yaml": "^3.12.0", + "make-dir": "^1.3.0", + "minimatch": "^3.0.4", + "once": "^1.4.0" + } + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==" + }, + "istanbul-lib-hook": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz", + "integrity": "sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA==", + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz", + "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==", + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" + } + }, + "istanbul-lib-report": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz", + "integrity": "sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA==", + "requires": { + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "supports-color": "^6.0.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz", + "integrity": "sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ==", + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "rimraf": "^2.6.2", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "istanbul-reports": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.1.1.tgz", + "integrity": "sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw==", + "requires": { + "handlebars": "^4.1.0" + } + }, + "jest": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.7.1.tgz", + "integrity": "sha512-AbvRar5r++izmqo5gdbAjTeA6uNRGoNRuj5vHB0OnDXo2DXWZJVuaObiGgtlvhKb+cWy2oYbQSfxv7Q7GjnAtA==", + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.7.1" + }, + "dependencies": { + "jest-cli": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.7.1.tgz", + "integrity": "sha512-32OBoSCVPzcTslGFl6yVCMzB2SqX3IrWwZCY5mZYkb0D2WsogmU3eV2o8z7+gRQa4o4sZPX/k7GU+II7CxM6WQ==", + "requires": { + "@jest/core": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^12.0.2" + } + } + } + }, + "jest-changed-files": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.7.0.tgz", + "integrity": "sha512-33BgewurnwSfJrW7T5/ZAXGE44o7swLslwh8aUckzq2e17/2Os1V0QU506ZNik3hjs8MgnEMKNkcud442NCDTw==", + "requires": { + "@jest/types": "^24.7.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.7.1.tgz", + "integrity": "sha512-8FlJNLI+X+MU37j7j8RE4DnJkvAghXmBWdArVzypW6WxfGuxiL/CCkzBg0gHtXhD2rxla3IMOSUAHylSKYJ83g==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.7.1", + "@jest/types": "^24.7.0", + "babel-jest": "^24.7.1", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.7.1", + "jest-environment-node": "^24.7.1", + "jest-get-type": "^24.3.0", + "jest-jasmine2": "^24.7.1", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.7.0", + "realpath-native": "^1.1.0" + } + }, + "jest-diff": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz", + "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==", + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-docblock": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.3.0.tgz", + "integrity": "sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg==", + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.7.1.tgz", + "integrity": "sha512-4fsS8fEfLa3lfnI1Jw6NxjhyRTgfpuOVTeUZZFyVYqeTa4hPhr2YkToUhouuLTrL2eMGOfpbdMyRx0GQ/VooKA==", + "requires": { + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.3.0", + "jest-util": "^24.7.1", + "pretty-format": "^24.7.0" + } + }, + "jest-environment-jsdom": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.7.1.tgz", + "integrity": "sha512-Gnhb+RqE2JuQGb3kJsLF8vfqjt3PHKSstq4Xc8ic+ax7QKo4Z0RWGucU3YV+DwKR3T9SYc+3YCUQEJs8r7+Jxg==", + "requires": { + "@jest/environment": "^24.7.1", + "@jest/fake-timers": "^24.7.1", + "@jest/types": "^24.7.0", + "jest-mock": "^24.7.0", + "jest-util": "^24.7.1", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.7.1.tgz", + "integrity": "sha512-GJJQt1p9/C6aj6yNZMvovZuxTUd+BEJprETdvTKSb4kHcw4mFj8777USQV0FJoJ4V3djpOwA5eWyPwfq//PFBA==", + "requires": { + "@jest/environment": "^24.7.1", + "@jest/fake-timers": "^24.7.1", + "@jest/types": "^24.7.0", + "jest-mock": "^24.7.0", + "jest-util": "^24.7.1" + } + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==" + }, + "jest-haste-map": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.7.1.tgz", + "integrity": "sha512-g0tWkzjpHD2qa03mTKhlydbmmYiA2KdcJe762SbfFo/7NIMgBWAA0XqQlApPwkWOF7Cxoi/gUqL0i6DIoLpMBw==", + "requires": { + "@jest/types": "^24.7.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.4.0", + "jest-util": "^24.7.1", + "jest-worker": "^24.6.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.7.1.tgz", + "integrity": "sha512-Y/9AOJDV1XS44wNwCaThq4Pw3gBPiOv/s6NcbOAkVRRUEPu+36L2xoPsqQXsDrxoBerqeyslpn2TpCI8Zr6J2w==", + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.7.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.7.1", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-runtime": "^24.7.1", + "jest-snapshot": "^24.7.1", + "jest-util": "^24.7.1", + "pretty-format": "^24.7.0", + "throat": "^4.0.0" + } + }, + "jest-leak-detector": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.7.0.tgz", + "integrity": "sha512-zV0qHKZGXtmPVVzT99CVEcHE9XDf+8LwiE0Ob7jjezERiGVljmqKFWpV2IkG+rkFIEUHFEkMiICu7wnoPM/RoQ==", + "requires": { + "pretty-format": "^24.7.0" + } + }, + "jest-matcher-utils": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz", + "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==", + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.7.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-message-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", + "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-mock": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.7.0.tgz", + "integrity": "sha512-6taW4B4WUcEiT2V9BbOmwyGuwuAFT2G8yghF7nyNW1/2gq5+6aTqSPcS9lS6ArvEkX55vbPAS/Jarx5LSm4Fng==", + "requires": { + "@jest/types": "^24.7.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==" + }, + "jest-regex-util": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.3.0.tgz", + "integrity": "sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg==" + }, + "jest-resolve": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.7.1.tgz", + "integrity": "sha512-Bgrc+/UUZpGJ4323sQyj85hV9d+ANyPNu6XfRDUcyFNX1QrZpSoM0kE4Mb2vZMAYTJZsBFzYe8X1UaOkOELSbw==", + "requires": { + "@jest/types": "^24.7.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + } + }, + "jest-resolve-dependencies": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.7.1.tgz", + "integrity": "sha512-2Eyh5LJB2liNzfk4eo7bD1ZyBbqEJIyyrFtZG555cSWW9xVHxII2NuOkSl1yUYTAYCAmM2f2aIT5A7HzNmubyg==", + "requires": { + "@jest/types": "^24.7.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.7.1" + } + }, + "jest-runner": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.7.1.tgz", + "integrity": "sha512-aNFc9liWU/xt+G9pobdKZ4qTeG/wnJrJna3VqunziDNsWT3EBpmxXZRBMKCsNMyfy+A/XHiV+tsMLufdsNdgCw==", + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.7.1", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.7.1", + "jest-jasmine2": "^24.7.1", + "jest-leak-detector": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-resolve": "^24.7.1", + "jest-runtime": "^24.7.1", + "jest-util": "^24.7.1", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + } + }, + "jest-runtime": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.7.1.tgz", + "integrity": "sha512-0VAbyBy7tll3R+82IPJpf6QZkokzXPIS71aDeqh+WzPRXRCNz6StQ45otFariPdJ4FmXpDiArdhZrzNAC3sj6A==", + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.7.1", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/yargs": "^12.0.2", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.7.1", + "jest-haste-map": "^24.7.1", + "jest-message-util": "^24.7.1", + "jest-mock": "^24.7.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.7.1", + "jest-snapshot": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^12.0.2" + } + }, + "jest-serializer": { + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.4.0.tgz", + "integrity": "sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q==" + }, + "jest-snapshot": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.7.1.tgz", + "integrity": "sha512-8Xk5O4p+JsZZn4RCNUS3pxA+ORKpEKepE+a5ejIKrId9CwrVN0NY+vkqEkXqlstA5NMBkNahXkR/4qEBy0t5yA==", + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "expect": "^24.7.1", + "jest-diff": "^24.7.0", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-resolve": "^24.7.1", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.7.0", + "semver": "^5.5.0" + } + }, + "jest-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.7.1.tgz", + "integrity": "sha512-/KilOue2n2rZ5AnEBYoxOXkeTu6vi7cjgQ8MXEkih0oeAXT6JkS3fr7/j8+engCjciOU1Nq5loMSKe0A1oeX0A==", + "requires": { + "@jest/console": "^24.7.1", + "@jest/fake-timers": "^24.7.1", + "@jest/source-map": "^24.3.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "jest-validate": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.7.0.tgz", + "integrity": "sha512-cgai/gts9B2chz1rqVdmLhzYxQbgQurh1PEQSvSgPZ8KGa1AqXsqC45W5wKEwzxKrWqypuQrQxnF4+G9VejJJA==", + "requires": { + "@jest/types": "^24.7.0", + "camelcase": "^5.0.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.3.0", + "leven": "^2.1.0", + "pretty-format": "^24.7.0" + } + }, + "jest-watcher": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.7.1.tgz", + "integrity": "sha512-Wd6TepHLRHVKLNPacEsBwlp9raeBIO+01xrN24Dek4ggTS8HHnOzYSFnvp+6MtkkJ3KfMzy220KTi95e2rRkrw==", + "requires": { + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/yargs": "^12.0.9", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.7.1", + "string-length": "^2.0.0" + } + }, + "jest-worker": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.6.0.tgz", + "integrity": "sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==", + "requires": { + "merge-stream": "^1.0.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "requires": { + "invert-kv": "^2.0.0" + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==" + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=" + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "requires": { + "chalk": "^2.0.1" + } + }, + "loglevel": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", + "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=" + }, + "loglevelnext": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", + "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", + "requires": { + "es6-symbol": "^3.1.1", + "object.assign": "^4.1.0" + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==" + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "requires": { + "tmpl": "1.0.x" + } + }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==" + }, + "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==", + "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", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz", + "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==", + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.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", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "requires": { + "readable-stream": "^2.0.1" + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" + }, + "mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "requires": { + "mime-db": "~1.38.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "mini-css-extract-plugin": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz", + "integrity": "sha512-IuaLjruM0vMKhUUT51fQdQzBYTX49dLj8w68ALEAe2A4iYNpIC4eMac67mt3NzycvjOlf07/kYxJDc0RTl1Wqw==", + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "nan": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node-forge": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==" + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" + }, + "node-libs-browser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", + "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.0", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=" + }, + "node-notifier": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz", + "integrity": "sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==", + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "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=" + }, + "nwsapi": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.3.tgz", + "integrity": "sha512-RowAaJGEgYXEZfQ7tvvdtAQUKPyTR6T6wNu0fwlNsGQYr/h3yQc6oI8WnVZh3Y/Sylwc+dtAlvPqfFZjhTyk3A==" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "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==", + "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=" + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==" + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==" + }, + "pako": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", + "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-asn1": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", + "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", + "requires": { + "asn1.js": "^4.0.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" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "^3.0.0" + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" + }, + "portfinder": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz", + "integrity": "sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==", + "requires": { + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "postcss": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-load-config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", + "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", + "requires": { + "cosmiconfig": "^4.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", + "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0", + "postcss-value-parser": "^3.3.1" + } + }, + "postcss-modules-scope": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", + "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", + "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", + "requires": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^7.0.6" + } + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "prettier": { + "version": "1.16.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", + "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==" + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + } + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "prompts": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.0.4.tgz", + "integrity": "sha512-HTzM3UWp/99A0gk51gAegwo1QRYA7xjcZufMNe33rCclFszUYAuHe1fIN/3ZmiHeGPkUsNaRyQm1hHOfM0PKxA==", + "requires": { + "kleur": "^3.0.2", + "sisteransi": "^1.0.0" + } + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "querystringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", + "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==" + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "requires": { + "util.promisify": "^1.0.0" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } + } + }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "requires": { + "lodash": "^4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "requires": { + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "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=" + }, + "requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==" + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rsvp": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.4.tgz", + "integrity": "sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==" + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + }, + "selfsigned": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", + "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==", + "requires": { + "node-forge": "0.7.5" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + } + }, + "serialize-javascript": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", + "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==" + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "sisteransi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.0.tgz", + "integrity": "sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ==" + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "requires": { + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" + } + }, + "sockjs-client": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", + "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", + "requires": { + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==" + }, + "spdy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", + "integrity": "sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==", + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "readable-stream": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", + "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-tree": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" + }, + "table": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", + "requires": { + "ajv": "^6.9.1", + "lodash": "^4.17.11", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "tapable": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", + "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==" + }, + "terser": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", + "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", + "requires": { + "commander": "^2.19.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.10" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "terser-webpack-plugin": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz", + "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==", + "requires": { + "cacache": "^11.0.2", + "find-cache-dir": "^2.0.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "terser": "^3.16.1", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "test-exclude": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.1.0.tgz", + "integrity": "sha512-gwf0S2fFsANC55fSeSqpb8BYk6w3FDvwZxfNjeF6FRgvFa43r+7wRiA/Q0IxoRU37wB/LE8IQ4221BsNucTaCA==", + "requires": { + "arrify": "^1.0.1", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^1.0.1" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", + "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==" + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "requires": { + "punycode": "^2.1.0" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "ts-jest": { + "version": "24.0.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-24.0.2.tgz", + "integrity": "sha512-h6ZCZiA1EQgjczxq+uGLXQlNgeg02WWJBbeT8j6nyIBRQdglqbvzDoHahTEIiS6Eor6x8mK6PfZ7brQ9Q6tzHw==", + "requires": { + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "json5": "2.x", + "make-error": "1.x", + "mkdirp": "0.x", + "resolve": "1.x", + "semver": "^5.5", + "yargs-parser": "10.x" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "requires": { + "minimist": "^1.2.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "tsutils": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.10.0.tgz", + "integrity": "sha512-q20XSMq7jutbGB8luhKKsQldRKWvyBO2BGqni3p4yq8Ys9bEP/xQw3KepKmMRt9gJ4lvQSScrihJrcKdKoSU7Q==", + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typescript": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.3.tgz", + "integrity": "sha512-FFgHdPt4T/duxx6Ndf7hwgMZZjZpB+U0nMNGVCYPq0rEzWKjEDobm4J6yb3CS7naZ0yURFqdw9Gwc7UOh/P9oQ==" + }, + "uglify-js": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.4.tgz", + "integrity": "sha512-GpKo28q/7Bm5BcX9vOu4S46FwisbPbAmkkqPnGIpKvKTM96I85N6XHQV+k4I6FA2wxgLhcsSyHoNhzucwCflvA==", + "optional": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", + "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "url-loader": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", + "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", + "requires": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==" + } + } + }, + "url-parse": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.5.tgz", + "integrity": "sha512-4XDvC5vZRjEpjP0L4znrWeoH8P8F0XGBlfLdABi/6oV4o8xUVbTpyrxWHxkK2bT0pSIpcjdIzSoWUhlUfawCAQ==", + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "v8-compile-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", + "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "requires": { + "indexof": "0.0.1" + } + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "requires": { + "makeerror": "1.0.x" + } + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "webpack": { + "version": "4.29.6", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.6.tgz", + "integrity": "sha512-MwBwpiE1BQpMDkbnUUaW6K8RFZjljJHArC6tWQJoFm0oQtfoSebtg4Y7/QHnJ/SddtjYLHaKGX64CFjG5rehJw==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.0.5", + "acorn-dynamic-import": "^4.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", + "mkdirp": "~0.5.0", + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^1.0.0", + "tapable": "^1.1.0", + "terser-webpack-plugin": "^1.1.0", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" + } + }, + "webpack-cli": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.0.tgz", + "integrity": "sha512-t1M7G4z5FhHKJ92WRKwZ1rtvi7rHc0NZoZRbSkol0YKl4HvcC8+DsmGDmK7MmZxHSAetHagiOsjOB6MmzC2TUw==", + "requires": { + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.0", + "findup-sync": "^2.0.0", + "global-modules": "^1.0.0", + "import-local": "^2.0.0", + "interpret": "^1.1.0", + "loader-utils": "^1.1.0", + "supports-color": "^5.5.0", + "v8-compile-cache": "^2.0.2", + "yargs": "^12.0.5" + } + }, + "webpack-dev-middleware": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.6.2.tgz", + "integrity": "sha512-A47I5SX60IkHrMmZUlB0ZKSWi29TZTcPz7cha1Z75yYOsgWh/1AcPmQEbC8ZIbU3A1ytSv1PMU0PyPz2Lmz2jg==", + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.3.1", + "range-parser": "^1.0.3", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "mime": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz", + "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==" + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + } + } + }, + "webpack-dev-server": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.3.1.tgz", + "integrity": "sha512-jY09LikOyGZrxVTXK0mgIq9y2IhCoJ05848dKZqX1gAGLU1YDqgpOT71+W53JH/wI4v6ky4hm+KvSyW14JEs5A==", + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.5", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.0", + "express": "^4.16.4", + "html-entities": "^1.2.1", + "http-proxy-middleware": "^0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.2.0", + "ip": "^1.1.5", + "killable": "^1.0.1", + "loglevel": "^1.6.1", + "opn": "^5.5.0", + "portfinder": "^1.0.20", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.4", + "semver": "^6.0.0", + "serve-index": "^1.9.1", + "sockjs": "0.3.19", + "sockjs-client": "1.3.0", + "spdy": "^4.0.0", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.6.2", + "webpack-log": "^2.0.0", + "yargs": "12.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "chokidar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "upath": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==" + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + } + } + }, + "webpack-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", + "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "loglevelnext": "^1.0.1", + "uuid": "^3.1.0" + } + }, + "webpack-sources": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "requires": { + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "worker-farm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "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=" + }, + "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=", + "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=", + "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=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "requires": { + "mkdirp": "^0.5.1" + } + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/visual_console_client/package.json b/visual_console_client/package.json new file mode 100644 index 0000000000..d049a39b10 --- /dev/null +++ b/visual_console_client/package.json @@ -0,0 +1,50 @@ +{ + "name": "pandora-fms-visual-console", + "version": "1.0.0", + "description": "Visual Console", + "scripts": { + "build": "BUILD_PATH=\"pandora_console/include/visual-console-client\" NODE_ENV=production webpack", + "build:dev": "BUILD_PATH=\"pandora_console/include/visual-console-client\" NODE_ENV=development webpack", + "build:watch": "npm run build -- --watch", + "format": "prettier", + "lint": "eslint \"src/**/*.ts\"", + "start": "webpack-dev-server --color --mode=development", + "test": "jest", + "test:watch": "jest --watch" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/pandorafms/pandorafms.git" + }, + "author": "Alejandro Gallardo Escobar ", + "license": "GPL2", + "private": true, + "bugs": { + "url": "https://github.com/pandorafms/pandorafms/issues" + }, + "homepage": "https://github.com/pandorafms/pandorafms#readme", + "dependencies": { + "@types/d3-shape": "^1.3.1", + "@types/jest": "^24.0.11", + "@typescript-eslint/eslint-plugin": "^1.6.0", + "@typescript-eslint/parser": "^1.6.0", + "awesome-typescript-loader": "^5.2.1", + "clean-webpack-plugin": "^2.0.1", + "css-loader": "^2.1.1", + "d3-shape": "^1.3.5", + "eslint": "^5.16.0", + "eslint-config-prettier": "^4.1.0", + "eslint-plugin-prettier": "^3.0.1", + "file-loader": "^3.0.1", + "jest": "^24.7.1", + "mini-css-extract-plugin": "^0.5.0", + "postcss-loader": "^3.0.0", + "prettier": "^1.16.1", + "ts-jest": "^24.0.2", + "typescript": "^3.4.3", + "url-loader": "^1.1.2", + "webpack": "^4.29.6", + "webpack-cli": "^3.3.0", + "webpack-dev-server": "^3.3.1" + } +} diff --git a/visual_console_client/playground/index.html b/visual_console_client/playground/index.html new file mode 100644 index 0000000000..a42ddd5907 --- /dev/null +++ b/visual_console_client/playground/index.html @@ -0,0 +1,365 @@ + + + + + + Visual Console Sandbox + + + + + +
      + + + + diff --git a/visual_console_client/src/Item.ts b/visual_console_client/src/Item.ts new file mode 100644 index 0000000000..2b635627c0 --- /dev/null +++ b/visual_console_client/src/Item.ts @@ -0,0 +1,553 @@ +import { Position, Size, UnknownObject, WithModuleProps } from "./types"; +import { + sizePropsDecoder, + positionPropsDecoder, + parseIntOr, + parseBoolean, + notEmptyStringOr, + replaceMacros, + humanDate, + humanTime +} from "./lib"; +import TypedEvent, { Listener, Disposable } from "./TypedEvent"; + +// Enum: https://www.typescriptlang.org/docs/handbook/enums.html. +export const enum ItemType { + STATIC_GRAPH = 0, + MODULE_GRAPH = 1, + SIMPLE_VALUE = 2, + PERCENTILE_BAR = 3, + LABEL = 4, + ICON = 5, + SIMPLE_VALUE_MAX = 6, + SIMPLE_VALUE_MIN = 7, + SIMPLE_VALUE_AVG = 8, + PERCENTILE_BUBBLE = 9, + SERVICE = 10, + GROUP_ITEM = 11, + BOX_ITEM = 12, + LINE_ITEM = 13, + AUTO_SLA_GRAPH = 14, + CIRCULAR_PROGRESS_BAR = 15, + CIRCULAR_INTERIOR_PROGRESS_BAR = 16, + DONUT_GRAPH = 17, + BARS_GRAPH = 18, + CLOCK = 19, + COLOR_CLOUD = 20 +} + +// Base item properties. This interface should be extended by the item implementations. +export interface ItemProps extends Position, Size { + readonly id: number; + readonly type: ItemType; + label: string | null; + labelPosition: "up" | "right" | "down" | "left"; + isLinkEnabled: boolean; + link: string | null; + isOnTop: boolean; + parentId: number | null; + aclGroupId: number | null; +} + +// FIXME: Fix type compatibility. +export interface ItemClickEvent { + // data: Props; + data: UnknownObject; + nativeEvent: Event; +} + +// FIXME: Fix type compatibility. +export interface ItemRemoveEvent { + // data: Props; + data: UnknownObject; +} + +/** + * Extract a valid enum value from a raw label positi9on value. + * @param labelPosition Raw value. + */ +const parseLabelPosition = ( + labelPosition: any // eslint-disable-line @typescript-eslint/no-explicit-any +): ItemProps["labelPosition"] => { + switch (labelPosition) { + case "up": + case "right": + case "down": + case "left": + return labelPosition; + default: + return "down"; + } +}; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the item props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function itemBasePropsDecoder(data: UnknownObject): ItemProps | never { + if (data.id == null || isNaN(parseInt(data.id))) { + throw new TypeError("invalid id."); + } + if (data.type == null || isNaN(parseInt(data.type))) { + throw new TypeError("invalid type."); + } + + return { + id: parseInt(data.id), + type: parseInt(data.type), + label: notEmptyStringOr(data.label, null), + labelPosition: parseLabelPosition(data.labelPosition), + isLinkEnabled: parseBoolean(data.isLinkEnabled), + link: notEmptyStringOr(data.link, null), + isOnTop: parseBoolean(data.isOnTop), + parentId: parseIntOr(data.parentId, null), + aclGroupId: parseIntOr(data.aclGroupId, null), + ...sizePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + ...positionPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +/** + * Base class of the visual console items. Should be extended to use its capabilities. + */ +abstract class VisualConsoleItem { + // Properties of the item. + private itemProps: Props; + // Reference to the DOM element which will contain the item. + public elementRef: HTMLElement; + public readonly labelElementRef: HTMLElement; + // Reference to the DOM element which will contain the view of the item which extends this class. + protected readonly childElementRef: HTMLElement; + // Event manager for click events. + private readonly clickEventManager = new TypedEvent>(); + // Event manager for remove events. + private readonly removeEventManager = new TypedEvent< + ItemRemoveEvent + >(); + // List of references to clean the event listeners. + private readonly disposables: Disposable[] = []; + + /** + * To create a new element which will be inside the item box. + * @return Item. + */ + protected abstract createDomElement(): HTMLElement; + + public constructor(props: Props) { + this.itemProps = props; + + /* + * Get a HTMLElement which represents the container box + * of the Visual Console item. This element will manage + * all the common things like click events, show a border + * when hovered, etc. + */ + this.elementRef = this.createContainerDomElement(); + this.labelElementRef = this.createLabelDomElement(); + + /* + * Get a HTMLElement which represents the custom view + * of the Visual Console item. This element will be + * different depending on the item implementation. + */ + this.childElementRef = this.createDomElement(); + + // Insert the elements into the container. + this.elementRef.append(this.childElementRef, this.labelElementRef); + + // Resize element. + this.resizeElement(props.width, props.height); + // Set label position. + this.changeLabelPosition(props.labelPosition); + } + + /** + * To create a new box for the visual console item. + * @return Item box. + */ + private createContainerDomElement(): HTMLElement { + let box; + if (this.props.isLinkEnabled) { + box = document.createElement("a"); + box as HTMLAnchorElement; + if (this.props.link) box.href = this.props.link; + } else { + box = document.createElement("div"); + box as HTMLDivElement; + } + + box.className = "visual-console-item"; + box.style.zIndex = this.props.isOnTop ? "2" : "1"; + box.style.left = `${this.props.x}px`; + box.style.top = `${this.props.y}px`; + box.onclick = e => + this.clickEventManager.emit({ data: this.props, nativeEvent: e }); + + return box; + } + + /** + * To create a new label for the visual console item. + * @return Item label. + */ + protected createLabelDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "visual-console-item-label"; + // Add the label if it exists. + const label = this.getLabelWithMacrosReplaced(); + if (label.length > 0) { + // Ugly table we need to use to replicate the legacy style. + const table = document.createElement("table"); + const row = document.createElement("tr"); + const emptyRow1 = document.createElement("tr"); + const emptyRow2 = document.createElement("tr"); + const cell = document.createElement("td"); + + cell.innerHTML = label; + row.append(cell); + table.append(emptyRow1, row, emptyRow2); + table.style.textAlign = "center"; + + // Change the table size depending on its position. + switch (this.props.labelPosition) { + case "up": + case "down": + if (this.props.width > 0) { + table.style.width = `${this.props.width}px`; + table.style.height = null; + } + break; + case "left": + case "right": + if (this.props.height > 0) { + table.style.width = null; + table.style.height = `${this.props.height}px`; + } + break; + } + + // element.innerHTML = this.props.label; + element.append(table); + } + + return element; + } + + /** + * Return the label stored into the props with some macros replaced. + */ + protected getLabelWithMacrosReplaced(): string { + // We assert that the props may have some needed properties. + const props = this.props as Partial; + + return replaceMacros( + [ + { + macro: "_date_", + value: humanDate(new Date()) + }, + { + macro: "_time_", + value: humanTime(new Date()) + }, + { + macro: "_agent_", + value: props.agentAlias != null ? props.agentAlias : "" + }, + { + macro: "_agentdescription_", + value: props.agentDescription != null ? props.agentDescription : "" + }, + { + macro: "_address_", + value: props.agentAddress != null ? props.agentAddress : "" + }, + { + macro: "_module_", + value: props.moduleName != null ? props.moduleName : "" + }, + { + macro: "_moduledescription_", + value: props.moduleDescription != null ? props.moduleDescription : "" + } + ], + this.props.label || "" + ); + } + + /** + * To update the content element. + * @return Item. + */ + protected updateDomElement(element: HTMLElement): void { + element.innerHTML = this.createDomElement().innerHTML; + } + + /** + * Public accessor of the `props` property. + * @return Properties. + */ + public get props(): Props { + return { ...this.itemProps }; // Return a copy. + } + + /** + * Public setter of the `props` property. + * If the new props are different enough than the + * stored props, a render would be fired. + * @param newProps + */ + public set props(newProps: Props) { + const prevProps = this.props; + // Update the internal props. + this.itemProps = newProps; + + // From this point, things which rely on this.props can access to the changes. + + // Check if we should re-render. + if (this.shouldBeUpdated(prevProps, newProps)) this.render(prevProps); + } + + /** + * To compare the previous and the new props and returns a boolean value + * in case the difference is meaningfull enough to perform DOM changes. + * + * Here, the only comparision is done by reference. + * + * Override this function to perform a different comparision depending on the item needs. + * + * @param prevProps + * @param newProps + * @return Whether the difference is meaningful enough to perform DOM changes or not. + */ + protected shouldBeUpdated(prevProps: Props, newProps: Props): boolean { + return prevProps !== newProps; + } + + /** + * To recreate or update the HTMLElement which represents the item into the DOM. + * @param prevProps If exists it will be used to only perform DOM updates instead of a full replace. + */ + public render(prevProps: Props | null = null): void { + this.updateDomElement(this.childElementRef); + + // Move box. + if (!prevProps || this.positionChanged(prevProps, this.props)) { + this.moveElement(this.props.x, this.props.y); + } + // Resize box. + if (!prevProps || this.sizeChanged(prevProps, this.props)) { + this.resizeElement(this.props.width, this.props.height); + } + // Change label. + const oldLabelHtml = this.labelElementRef.innerHTML; + const newLabelHtml = this.createLabelDomElement().innerHTML; + if (oldLabelHtml !== newLabelHtml) { + this.labelElementRef.innerHTML = newLabelHtml; + } + // Change label position. + if (!prevProps || prevProps.labelPosition !== this.props.labelPosition) { + this.changeLabelPosition(this.props.labelPosition); + } + // Change link. + if ( + prevProps && + (prevProps.isLinkEnabled !== this.props.isLinkEnabled || + (this.props.isLinkEnabled && prevProps.link !== this.props.link)) + ) { + const container = this.createContainerDomElement(); + // Add the children of the old element. + container.innerHTML = this.elementRef.innerHTML; + // Copy the attributes. + const attrs = this.elementRef.attributes; + for (let i = 0; i < attrs.length; i++) { + if (attrs[i].nodeName !== "id") { + container.setAttributeNode(attrs[i]); + } + } + // Replace the reference. + if (this.elementRef.parentNode !== null) { + this.elementRef.parentNode.replaceChild(container, this.elementRef); + } + + // Changed the reference to the main element. It's ugly, but needed. + this.elementRef = container; + } + } + + /** + * To remove the event listeners and the elements from the DOM. + */ + public remove(): void { + // Call the remove event. + this.removeEventManager.emit({ data: this.props }); + // Event listeners. + this.disposables.forEach(disposable => { + try { + disposable.dispose(); + } catch (ignored) {} // eslint-disable-line no-empty + }); + // VisualConsoleItem DOM element. + this.elementRef.remove(); + } + + /** + * Compare the previous and the new position and return + * a boolean value in case the position changed. + * @param prevPosition + * @param newPosition + * @return Whether the position changed or not. + */ + protected positionChanged( + prevPosition: Position, + newPosition: Position + ): boolean { + return prevPosition.x !== newPosition.x || prevPosition.y !== newPosition.y; + } + + /** + * Move the label around the item content. + * @param position Label position. + */ + protected changeLabelPosition(position: Props["labelPosition"]): void { + switch (position) { + case "up": + this.elementRef.style.flexDirection = "column-reverse"; + break; + case "left": + this.elementRef.style.flexDirection = "row-reverse"; + break; + case "right": + this.elementRef.style.flexDirection = "row"; + break; + case "down": + default: + this.elementRef.style.flexDirection = "column"; + break; + } + + // Ugly table to show the label as its legacy counterpart. + const tables = this.labelElementRef.getElementsByTagName("table"); + const table = tables.length > 0 ? tables.item(0) : null; + // Change the table size depending on its position. + if (table) { + switch (this.props.labelPosition) { + case "up": + case "down": + if (this.props.width > 0) { + table.style.width = `${this.props.width}px`; + table.style.height = null; + } + break; + case "left": + case "right": + if (this.props.height > 0) { + table.style.width = null; + table.style.height = `${this.props.height}px`; + } + break; + } + } + } + + /** + * Move the DOM container. + * @param x Horizontal axis position. + * @param y Vertical axis position. + */ + protected moveElement(x: number, y: number): void { + this.elementRef.style.left = `${x}px`; + this.elementRef.style.top = `${y}px`; + } + + /** + * Update the position into the properties and move the DOM container. + * @param x Horizontal axis position. + * @param y Vertical axis position. + */ + public move(x: number, y: number): void { + this.moveElement(x, y); + this.itemProps = { + ...this.props, // Object spread: http://es6-features.org/#SpreadOperator + x, + y + }; + } + + /** + * Compare the previous and the new size and return + * a boolean value in case the size changed. + * @param prevSize + * @param newSize + * @return Whether the size changed or not. + */ + protected sizeChanged(prevSize: Size, newSize: Size): boolean { + return ( + prevSize.width !== newSize.width || prevSize.height !== newSize.height + ); + } + + /** + * Resize the DOM content container. + * @param width + * @param height + */ + protected resizeElement(width: number, height: number): void { + // The most valuable size is the content size. + this.childElementRef.style.width = width > 0 ? `${width}px` : null; + this.childElementRef.style.height = height > 0 ? `${height}px` : null; + } + + /** + * Update the size into the properties and resize the DOM container. + * @param width + * @param height + */ + public resize(width: number, height: number): void { + this.resizeElement(width, height); + this.itemProps = { + ...this.props, // Object spread: http://es6-features.org/#SpreadOperator + width, + height + }; + } + + /** + * To add an event handler to the click of the linked visual console elements. + * @param listener Function which is going to be executed when a linked console is clicked. + */ + public onClick(listener: Listener>): Disposable { + /* + * The '.on' function returns a function which will clean the event + * listener when executed. We store all the 'dispose' functions to + * call them when the item should be cleared. + */ + const disposable = this.clickEventManager.on(listener); + this.disposables.push(disposable); + + return disposable; + } + + /** + * To add an event handler to the removal of the item. + * @param listener Function which is going to be executed when a item is removed. + */ + public onRemove(listener: Listener>): Disposable { + /* + * The '.on' function returns a function which will clean the event + * listener when executed. We store all the 'dispose' functions to + * call them when the item should be cleared. + */ + const disposable = this.removeEventManager.on(listener); + this.disposables.push(disposable); + + return disposable; + } +} + +export default VisualConsoleItem; diff --git a/visual_console_client/src/TypedEvent.ts b/visual_console_client/src/TypedEvent.ts new file mode 100644 index 0000000000..e199470f6c --- /dev/null +++ b/visual_console_client/src/TypedEvent.ts @@ -0,0 +1,40 @@ +export interface Listener { + (event: T): void; +} + +export interface Disposable { + dispose: () => void; +} + +/** passes through events as they happen. You will not get events from before you start listening */ +export default class TypedEvent { + private listeners: Listener[] = []; + private listenersOncer: Listener[] = []; + + public on = (listener: Listener): Disposable => { + this.listeners.push(listener); + return { + dispose: () => this.off(listener) + }; + }; + + public once = (listener: Listener): void => { + this.listenersOncer.push(listener); + }; + + public off = (listener: Listener): void => { + const callbackIndex = this.listeners.indexOf(listener); + if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1); + }; + + public emit = (event: T): void => { + /** Update any general listeners */ + this.listeners.forEach(listener => listener(event)); + + /** Clear the `once` queue */ + this.listenersOncer.forEach(listener => listener(event)); + this.listenersOncer = []; + }; + + public pipe = (te: TypedEvent): Disposable => this.on(e => te.emit(e)); +} diff --git a/visual_console_client/src/VisualConsole.ts b/visual_console_client/src/VisualConsole.ts new file mode 100644 index 0000000000..7b45ccc2f1 --- /dev/null +++ b/visual_console_client/src/VisualConsole.ts @@ -0,0 +1,560 @@ +import { UnknownObject, Size } from "./types"; +import { + parseBoolean, + sizePropsDecoder, + parseIntOr, + notEmptyStringOr +} from "./lib"; +import Item, { + ItemType, + ItemProps, + ItemClickEvent, + ItemRemoveEvent +} from "./Item"; +import StaticGraph, { staticGraphPropsDecoder } from "./items/StaticGraph"; +import Icon, { iconPropsDecoder } from "./items/Icon"; +import ColorCloud, { colorCloudPropsDecoder } from "./items/ColorCloud"; +import Group, { groupPropsDecoder } from "./items/Group"; +import Clock, { clockPropsDecoder } from "./items/Clock"; +import Box, { boxPropsDecoder } from "./items/Box"; +import Line, { linePropsDecoder } from "./items/Line"; +import Label, { labelPropsDecoder } from "./items/Label"; +import SimpleValue, { simpleValuePropsDecoder } from "./items/SimpleValue"; +import EventsHistory, { + eventsHistoryPropsDecoder +} from "./items/EventsHistory"; +import Percentile, { percentilePropsDecoder } from "./items/Percentile"; +import TypedEvent, { Disposable, Listener } from "./TypedEvent"; +import DonutGraph, { donutGraphPropsDecoder } from "./items/DonutGraph"; +import BarsGraph, { barsGraphPropsDecoder } from "./items/BarsGraph"; +import ModuleGraph, { moduleGraphPropsDecoder } from "./items/ModuleGraph"; +import Service, { servicePropsDecoder } from "./items/Service"; + +// TODO: Document. +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +function itemInstanceFrom(data: UnknownObject) { + const type = parseIntOr(data.type, null); + if (type == null) throw new TypeError("missing item type."); + + switch (type as ItemType) { + case ItemType.STATIC_GRAPH: + return new StaticGraph(staticGraphPropsDecoder(data)); + case ItemType.MODULE_GRAPH: + return new ModuleGraph(moduleGraphPropsDecoder(data)); + case ItemType.SIMPLE_VALUE: + case ItemType.SIMPLE_VALUE_MAX: + case ItemType.SIMPLE_VALUE_MIN: + case ItemType.SIMPLE_VALUE_AVG: + return new SimpleValue(simpleValuePropsDecoder(data)); + case ItemType.PERCENTILE_BAR: + case ItemType.PERCENTILE_BUBBLE: + case ItemType.CIRCULAR_PROGRESS_BAR: + case ItemType.CIRCULAR_INTERIOR_PROGRESS_BAR: + return new Percentile(percentilePropsDecoder(data)); + case ItemType.LABEL: + return new Label(labelPropsDecoder(data)); + case ItemType.ICON: + return new Icon(iconPropsDecoder(data)); + case ItemType.SERVICE: + return new Service(servicePropsDecoder(data)); + case ItemType.GROUP_ITEM: + return new Group(groupPropsDecoder(data)); + case ItemType.BOX_ITEM: + return new Box(boxPropsDecoder(data)); + case ItemType.LINE_ITEM: + return new Line(linePropsDecoder(data)); + case ItemType.AUTO_SLA_GRAPH: + return new EventsHistory(eventsHistoryPropsDecoder(data)); + case ItemType.DONUT_GRAPH: + return new DonutGraph(donutGraphPropsDecoder(data)); + case ItemType.BARS_GRAPH: + return new BarsGraph(barsGraphPropsDecoder(data)); + case ItemType.CLOCK: + return new Clock(clockPropsDecoder(data)); + case ItemType.COLOR_CLOUD: + return new ColorCloud(colorCloudPropsDecoder(data)); + default: + throw new TypeError("item not found"); + } +} + +// TODO: Document. +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +function decodeProps(data: UnknownObject) { + const type = parseIntOr(data.type, null); + if (type == null) throw new TypeError("missing item type."); + + switch (type as ItemType) { + case ItemType.STATIC_GRAPH: + return staticGraphPropsDecoder(data); + case ItemType.MODULE_GRAPH: + return moduleGraphPropsDecoder(data); + case ItemType.SIMPLE_VALUE: + case ItemType.SIMPLE_VALUE_MAX: + case ItemType.SIMPLE_VALUE_MIN: + case ItemType.SIMPLE_VALUE_AVG: + return simpleValuePropsDecoder(data); + case ItemType.PERCENTILE_BAR: + case ItemType.PERCENTILE_BUBBLE: + case ItemType.CIRCULAR_PROGRESS_BAR: + case ItemType.CIRCULAR_INTERIOR_PROGRESS_BAR: + return percentilePropsDecoder(data); + case ItemType.LABEL: + return labelPropsDecoder(data); + case ItemType.ICON: + return iconPropsDecoder(data); + case ItemType.SERVICE: + return servicePropsDecoder(data); + case ItemType.GROUP_ITEM: + return groupPropsDecoder(data); + case ItemType.BOX_ITEM: + return boxPropsDecoder(data); + case ItemType.LINE_ITEM: + return linePropsDecoder(data); + case ItemType.AUTO_SLA_GRAPH: + return eventsHistoryPropsDecoder(data); + case ItemType.DONUT_GRAPH: + return donutGraphPropsDecoder(data); + case ItemType.BARS_GRAPH: + return barsGraphPropsDecoder(data); + case ItemType.CLOCK: + return clockPropsDecoder(data); + case ItemType.COLOR_CLOUD: + return colorCloudPropsDecoder(data); + default: + throw new TypeError("decoder not found"); + } +} + +// Base properties. +export interface VisualConsoleProps extends Size { + readonly id: number; + name: string; + groupId: number; + backgroundURL: string | null; // URL? + backgroundColor: string | null; + isFavorite: boolean; + relationLineWidth: number; +} + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the Visual Console props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function visualConsolePropsDecoder( + data: UnknownObject +): VisualConsoleProps | never { + // Object destructuring: http://es6-features.org/#ObjectMatchingShorthandNotation + const { + id, + name, + groupId, + backgroundURL, + backgroundColor, + isFavorite, + relationLineWidth + } = data; + + if (id == null || isNaN(parseInt(id))) { + throw new TypeError("invalid Id."); + } + if (typeof name !== "string" || name.length === 0) { + throw new TypeError("invalid name."); + } + if (groupId == null || isNaN(parseInt(groupId))) { + throw new TypeError("invalid group Id."); + } + + return { + id: parseInt(id), + name, + groupId: parseInt(groupId), + backgroundURL: notEmptyStringOr(backgroundURL, null), + backgroundColor: notEmptyStringOr(backgroundColor, null), + isFavorite: parseBoolean(isFavorite), + relationLineWidth: parseIntOr(relationLineWidth, 0), + ...sizePropsDecoder(data) + }; +} + +export default class VisualConsole { + // Reference to the DOM element which will contain the items. + private readonly containerRef: HTMLElement; + // Properties. + private _props: VisualConsoleProps; + // Visual Console Item instances by their Id. + private elementsById: { + [key: number]: Item; + } = {}; + // Visual Console Item Ids. + private elementIds: ItemProps["id"][] = []; + // Dictionary which store the created lines. + private relations: { + [key: string]: Line; + } = {}; + // Event manager for click events. + private readonly clickEventManager = new TypedEvent< + ItemClickEvent + >(); + // List of references to clean the event listeners. + private readonly disposables: Disposable[] = []; + + /** + * React to a click on an element. + * @param e Event object. + */ + private handleElementClick: (e: ItemClickEvent) => void = e => { + this.clickEventManager.emit(e); + // console.log(`Clicked element #${e.data.id}`, e); + }; + + /** + * Clear some element references. + * @param e Event object. + */ + private handleElementRemove: (e: ItemRemoveEvent) => void = e => { + // Remove the element from the list and its relations. + this.elementIds = this.elementIds.filter(id => id !== e.data.id); + delete this.elementsById[e.data.id]; + this.clearRelations(e.data.id); + }; + + public constructor( + container: HTMLElement, + props: UnknownObject, + items: UnknownObject[] + ) { + this.containerRef = container; + this._props = visualConsolePropsDecoder(props); + + // Force the first render. + this.render(); + + // Sort by isOnTop, id ASC + items = items.sort(function(a, b) { + if ( + a.isOnTop == null || + b.isOnTop == null || + a.id == null || + b.id == null + ) { + return 0; + } + + if (a.isOnTop && !b.isOnTop) return 1; + else if (!a.isOnTop && b.isOnTop) return -1; + else if (a.id > b.id) return 1; + else return -1; + }); + + // Initialize the items. + items.forEach(item => { + try { + const itemInstance = itemInstanceFrom(item); + // Add the item to the list. + this.elementsById[itemInstance.props.id] = itemInstance; + this.elementIds.push(itemInstance.props.id); + // Item event handlers. + itemInstance.onClick(this.handleElementClick); + itemInstance.onRemove(this.handleElementRemove); + // Add the item to the DOM. + this.containerRef.append(itemInstance.elementRef); + } catch (error) { + console.log("Error creating a new element:", error.message); + } + }); + + // Create lines. + this.buildRelations(); + } + + /** + * Public accessor of the `elements` property. + * @return Properties. + */ + public get elements(): Item[] { + // Ensure the type cause Typescript doesn't know the filter removes null items. + return this.elementIds + .map(id => this.elementsById[id]) + .filter(_ => _ != null) as Item[]; + } + + /** + * Public setter of the `elements` property. + * @param items. + */ + public updateElements(items: UnknownObject[]): void { + const itemIds = items.map(item => item.id || null).filter(id => id != null); + itemIds as number[]; // Tell the type system to rely on us. + // Get the elements we should delete. + const deletedIds: number[] = this.elementIds.filter( + id => itemIds.indexOf(id) < 0 + ); + // Delete the elements. + deletedIds.forEach(id => { + if (this.elementsById[id] != null) { + this.elementsById[id].remove(); + delete this.elementsById[id]; + } + }); + // Replace the element ids. + this.elementIds = itemIds; + + // Initialize the items. + items.forEach(item => { + if (item.id) { + if (this.elementsById[item.id] == null) { + // New item. + try { + const itemInstance = itemInstanceFrom(item); + // Add the item to the list. + this.elementsById[itemInstance.props.id] = itemInstance; + // Item event handlers. + itemInstance.onClick(this.handleElementClick); + itemInstance.onRemove(this.handleElementRemove); + // Add the item to the DOM. + this.containerRef.append(itemInstance.elementRef); + } catch (error) { + console.log("Error creating a new element:", error.message); + } + } else { + // Update item. + try { + this.elementsById[item.id].props = decodeProps(item); + } catch (error) { + console.log("Error updating an element:", error.message); + } + } + } + }); + + // Re-build relations. + this.buildRelations(); + } + + /** + * Public accessor of the `props` property. + * @return Properties. + */ + public get props(): VisualConsoleProps { + return { ...this._props }; // Return a copy. + } + + /** + * Public setter of the `props` property. + * If the new props are different enough than the + * stored props, a render would be fired. + * @param newProps + */ + public set props(newProps: VisualConsoleProps) { + const prevProps = this.props; + // Update the internal props. + this._props = newProps; + + // From this point, things which rely on this.props can access to the changes. + + // Re-render. + this.render(prevProps); + } + + /** + * Recreate or update the HTMLElement which represents the Visual Console into the DOM. + * @param prevProps If exists it will be used to only DOM updates instead of a full replace. + */ + public render(prevProps: VisualConsoleProps | null = null): void { + if (prevProps) { + if (prevProps.backgroundURL !== this.props.backgroundURL) { + this.containerRef.style.backgroundImage = + this.props.backgroundURL !== null + ? `url(${this.props.backgroundURL})` + : null; + } + if (prevProps.backgroundColor !== this.props.backgroundColor) { + this.containerRef.style.backgroundColor = this.props.backgroundColor; + } + if (this.sizeChanged(prevProps, this.props)) { + this.resizeElement(this.props.width, this.props.height); + } + } else { + this.containerRef.style.backgroundImage = + this.props.backgroundURL !== null + ? `url(${this.props.backgroundURL})` + : null; + + this.containerRef.style.backgroundColor = this.props.backgroundColor; + this.resizeElement(this.props.width, this.props.height); + } + } + + /** + * Compare the previous and the new size and return + * a boolean value in case the size changed. + * @param prevSize + * @param newSize + * @return Whether the size changed or not. + */ + public sizeChanged(prevSize: Size, newSize: Size): boolean { + return ( + prevSize.width !== newSize.width || prevSize.height !== newSize.height + ); + } + + /** + * Resize the DOM container. + * @param width + * @param height + */ + public resizeElement(width: number, height: number): void { + this.containerRef.style.width = `${width}px`; + this.containerRef.style.height = `${height}px`; + } + + /** + * Update the size into the properties and resize the DOM container. + * @param width + * @param height + */ + public resize(width: number, height: number): void { + this.props = { + ...this.props, // Object spread: http://es6-features.org/#SpreadOperator + width, + height + }; + } + + /** + * To remove the event listeners and the elements from the DOM. + */ + public remove(): void { + this.disposables.forEach(d => d.dispose()); // Arrow function. + this.elements.forEach(e => e.remove()); // Arrow function. + this.elementsById = {}; + this.elementIds = []; + // Clear relations. + this.clearRelations(); + // Clean container. + this.containerRef.innerHTML = ""; + } + + /** + * Create line elements which connect the elements with their parents. + */ + private buildRelations(): void { + // Clear relations. + this.clearRelations(); + // Add relations. + this.elements.forEach(item => { + if (item.props.parentId !== null) { + const parent = this.elementsById[item.props.parentId]; + const child = this.elementsById[item.props.id]; + if (parent && child) this.addRelationLine(parent, child); + } + }); + } + + /** + * @param itemId Optional identifier of a parent or child item. + * Remove the line elements which connect the elements with their parents. + */ + private clearRelations(itemId?: number): void { + if (itemId != null) { + for (let key in this.relations) { + const ids = key.split("|"); + const parentId = Number.parseInt(ids[0]); + const childId = Number.parseInt(ids[1]); + + if (itemId === parentId || itemId === childId) { + this.relations[key].remove(); + delete this.relations[key]; + } + } + } else { + for (let key in this.relations) { + this.relations[key].remove(); + delete this.relations[key]; + } + } + } + + /** + * Retrieve the line element which represent the relation between items. + * @param parentId Identifier of the parent item. + * @param childId Itentifier of the child item. + * @return The line element or nothing. + */ + private getRelationLine(parentId: number, childId: number): Line | null { + const identifier = `${parentId}|${childId}`; + return this.relations[identifier] || null; + } + + /** + * Add a new line item to represent a relation between the items. + * @param parent Parent item. + * @param child Child item. + * @return Whether the line was added or not. + */ + private addRelationLine( + parent: Item, + child: Item + ): Line { + const identifier = `${parent.props.id}|${child.props.id}`; + if (this.relations[identifier] != null) { + this.relations[identifier].remove(); + } + + // Get the items center. + const startX = parent.props.x + parent.elementRef.clientWidth / 2; + const startY = + parent.props.y + + (parent.elementRef.clientHeight - parent.labelElementRef.clientHeight) / + 2; + const endX = child.props.x + child.elementRef.clientWidth / 2; + const endY = + child.props.y + + (child.elementRef.clientHeight - child.labelElementRef.clientHeight) / 2; + + const line = new Line( + linePropsDecoder({ + id: 0, + type: ItemType.LINE_ITEM, + startX, + startY, + endX, + endY, + width: 0, + height: 0, + lineWidth: this.props.relationLineWidth, + color: "#CCCCCC" + }) + ); + // Save a reference to the line item. + this.relations[identifier] = line; + + // Add the line to the DOM. + line.elementRef.style.zIndex = "0"; + this.containerRef.append(line.elementRef); + + return line; + } + + /** + * Add an event handler to the click of the linked visual console elements. + * @param listener Function which is going to be executed when a linked console is clicked. + */ + public onClick(listener: Listener>): Disposable { + /* + * The '.on' function returns a function which will clean the event + * listener when executed. We store all the 'dispose' functions to + * call them when the item should be cleared. + */ + const disposable = this.clickEventManager.on(listener); + this.disposables.push(disposable); + + return disposable; + } +} diff --git a/visual_console_client/src/index.ts b/visual_console_client/src/index.ts new file mode 100644 index 0000000000..a7e8656d8d --- /dev/null +++ b/visual_console_client/src/index.ts @@ -0,0 +1,14 @@ +/* + * Useful resources. + * http://es6-features.org/ + * http://exploringjs.com/es6 + * https://www.typescriptlang.org/ + */ + +import "./main.css"; // CSS import. +import VisualConsole from "./VisualConsole"; + +// Export the VisualConsole class to the global object. + +// eslint-disable-next-line +(window as any).VisualConsole = VisualConsole; diff --git a/visual_console_client/src/items/BarsGraph.ts b/visual_console_client/src/items/BarsGraph.ts new file mode 100644 index 0000000000..d1a6fe97a5 --- /dev/null +++ b/visual_console_client/src/items/BarsGraph.ts @@ -0,0 +1,67 @@ +import { UnknownObject, WithModuleProps } from "../types"; +import { modulePropsDecoder, decodeBase64, stringIsEmpty } from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +export type BarsGraphProps = { + type: ItemType.BARS_GRAPH; + html: string; +} & ItemProps & + WithModuleProps; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the bars graph props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function barsGraphPropsDecoder( + data: UnknownObject +): BarsGraphProps | never { + if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) { + throw new TypeError("missing html content."); + } + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.BARS_GRAPH, + html: !stringIsEmpty(data.html) + ? data.html + : decodeBase64(data.encodedHtml), + ...modulePropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +export default class BarsGraph extends Item { + protected createDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "bars-graph"; + element.innerHTML = this.props.html; + + // Hack to execute the JS after the HTML is added to the DOM. + const scripts = element.getElementsByTagName("script"); + for (let i = 0; i < scripts.length; i++) { + setTimeout(() => { + if (scripts[i].src.length === 0) eval(scripts[i].innerHTML.trim()); + }, 0); + } + + return element; + } + + protected updateDomElement(element: HTMLElement): void { + element.innerHTML = this.props.html; + + // Hack to execute the JS after the HTML is added to the DOM. + const aux = document.createElement("div"); + aux.innerHTML = this.props.html; + const scripts = aux.getElementsByTagName("script"); + for (let i = 0; i < scripts.length; i++) { + if (scripts[i].src.length === 0) { + eval(scripts[i].innerHTML.trim()); + } + } + } +} diff --git a/visual_console_client/src/items/Box.ts b/visual_console_client/src/items/Box.ts new file mode 100644 index 0000000000..ca3078c0a6 --- /dev/null +++ b/visual_console_client/src/items/Box.ts @@ -0,0 +1,68 @@ +import { UnknownObject } from "../types"; +import { parseIntOr, notEmptyStringOr } from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +interface BoxProps extends ItemProps { + // Overrided properties. + readonly type: ItemType.BOX_ITEM; + label: null; + isLinkEnabled: false; + parentId: null; + aclGroupId: null; + // Custom properties. + borderWidth: number; + borderColor: string | null; + fillColor: string | null; +} + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the item props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function boxPropsDecoder(data: UnknownObject): BoxProps | never { + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.BOX_ITEM, + label: null, + isLinkEnabled: false, + parentId: null, + aclGroupId: null, + // Custom properties. + borderWidth: parseIntOr(data.borderWidth, 0), + borderColor: notEmptyStringOr(data.borderColor, null), + fillColor: notEmptyStringOr(data.fillColor, null) + }; +} + +export default class Box extends Item { + protected createDomElement(): HTMLElement { + const box: HTMLDivElement = document.createElement("div"); + box.className = "box"; + // To prevent this item to expand beyond its parent. + box.style.boxSizing = "border-box"; + + if (this.props.fillColor) { + box.style.backgroundColor = this.props.fillColor; + } + + // Border. + if (this.props.borderWidth > 0) { + box.style.borderStyle = "solid"; + // Control the max width to prevent this item to expand beyond its parent. + const maxBorderWidth = Math.min(this.props.width, this.props.height) / 2; + const borderWidth = Math.min(this.props.borderWidth, maxBorderWidth); + box.style.borderWidth = `${borderWidth}px`; + + if (this.props.borderColor) { + box.style.borderColor = this.props.borderColor; + } + } + + return box; + } +} diff --git a/visual_console_client/src/items/Clock/alarm-clock.ttf b/visual_console_client/src/items/Clock/alarm-clock.ttf new file mode 100755 index 0000000000..9e9b593459 Binary files /dev/null and b/visual_console_client/src/items/Clock/alarm-clock.ttf differ diff --git a/visual_console_client/src/items/Clock/index.ts b/visual_console_client/src/items/Clock/index.ts new file mode 100644 index 0000000000..a65f188659 --- /dev/null +++ b/visual_console_client/src/items/Clock/index.ts @@ -0,0 +1,601 @@ +import "./styles.css"; + +import { LinkedVisualConsoleProps, UnknownObject, Size } from "../../types"; +import { + linkedVCPropsDecoder, + parseIntOr, + parseBoolean, + prefixedCssRules, + notEmptyStringOr, + humanDate, + humanTime +} from "../../lib"; +import Item, { ItemProps, itemBasePropsDecoder, ItemType } from "../../Item"; + +export type ClockProps = { + type: ItemType.CLOCK; + clockType: "analogic" | "digital"; + clockFormat: "datetime" | "time"; + clockTimezone: string; + clockTimezoneOffset: number; // Offset of the timezone to UTC in seconds. + showClockTimezone: boolean; + color?: string | null; +} & ItemProps & + LinkedVisualConsoleProps; + +/** + * Extract a valid enum value from a raw unknown value. + * @param clockType Raw value. + */ +const parseClockType = ( + clockType: any // eslint-disable-line @typescript-eslint/no-explicit-any +): ClockProps["clockType"] => { + switch (clockType) { + case "analogic": + case "digital": + return clockType; + default: + return "analogic"; + } +}; + +/** + * Extract a valid enum value from a raw unknown value. + * @param clockFormat Raw value. + */ +const parseClockFormat = ( + clockFormat: any // eslint-disable-line @typescript-eslint/no-explicit-any +): ClockProps["clockFormat"] => { + switch (clockFormat) { + case "datetime": + case "date": + case "time": + return clockFormat; + default: + return "datetime"; + } +}; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the clock props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function clockPropsDecoder(data: UnknownObject): ClockProps | never { + if ( + typeof data.clockTimezone !== "string" || + data.clockTimezone.length === 0 + ) { + throw new TypeError("invalid timezone."); + } + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.CLOCK, + clockType: parseClockType(data.clockType), + clockFormat: parseClockFormat(data.clockFormat), + clockTimezone: data.clockTimezone, + clockTimezoneOffset: parseIntOr(data.clockTimezoneOffset, 0), + showClockTimezone: parseBoolean(data.showClockTimezone), + color: notEmptyStringOr(data.color, null), + ...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +export default class Clock extends Item { + public static readonly TICK_INTERVAL = 1000; // In ms. + private intervalRef: number | null = null; + + public constructor(props: ClockProps) { + // Call the superclass constructor. + super(props); + + /* The item is already loaded and inserted into the DOM. + * The class properties are now initialized. + * Now you can modify the item, add event handlers, timers, etc. + */ + + /* The use of the arrow function is important here. startTick will + * use the function passed as an argument to call the global setInterval + * function. The interval, timeout or event functions, among other, are + * called into another execution loop and using a different context. + * The arrow functions, unlike the classic functions, doesn't create + * their own context (this), so their context at execution time will be + * use the current context at the declaration time. + * http://es6-features.org/#Lexicalthis + */ + this.startTick( + () => { + // Replace the old element with the updated date. + this.childElementRef.innerHTML = this.createClock().innerHTML; + }, + /* The analogic clock doesn't need to tick, + * but it will be refreshed every 20 seconds + * to avoid a desync caused by page freezes. + */ + this.props.clockType === "analogic" ? 20000 : Clock.TICK_INTERVAL + ); + } + + /** + * Wrap a window.clearInterval call. + */ + private stopTick(): void { + if (this.intervalRef !== null) { + window.clearInterval(this.intervalRef); + this.intervalRef = null; + } + } + + /** + * Wrap a window.setInterval call. + * @param handler Function to be called every time the interval + * timer is reached. + * @param interval Number in milliseconds for the interval timer. + */ + private startTick( + handler: TimerHandler, + interval: number = Clock.TICK_INTERVAL + ): void { + this.stopTick(); + this.intervalRef = window.setInterval(handler, interval); + } + + /** + * Create a element which contains the DOM representation of the item. + * @return DOM Element. + * @override + */ + protected createDomElement(): HTMLElement | never { + return this.createClock(); + } + + /** + * To remove the event listeners and the elements from the DOM. + * @override + */ + public remove(): void { + // Clear the interval. + this.stopTick(); + // Call to the parent clean function. + super.remove(); + } + + /** + * @override Item.resizeElement + * Resize the DOM content container. + * @param width + * @param height + */ + protected resizeElement(width: number, height: number): void { + const { width: newWidth, height: newHeight } = this.getElementSize( + width, + height + ); // Destructuring assigment: http://es6-features.org/#ObjectMatchingShorthandNotation + super.resizeElement(newWidth, newHeight); + // Re-render the item to force it calculate a new font size. + if (this.props.clockType === "digital") { + // Replace the old element with the updated date. + this.childElementRef.innerHTML = this.createClock().innerHTML; + } + } + + /** + * Create a element which contains a representation of a clock. + * It choose between the clock types. + * @return DOM Element. + * @throws Error. + */ + private createClock(): HTMLElement | never { + switch (this.props.clockType) { + case "analogic": + return this.createAnalogicClock(); + case "digital": + return this.createDigitalClock(); + default: + throw new Error("invalid clock type."); + } + } + + /** + * Create a element which contains a representation of an analogic clock. + * @return DOM Element. + */ + private createAnalogicClock(): HTMLElement { + const svgNS = "http://www.w3.org/2000/svg"; + const colors = { + watchFace: "#FFFFF0", + watchFaceBorder: "#242124", + mark: "#242124", + handDark: "#242124", + handLight: "#525252", + secondHand: "#DC143C" + }; + + const { width, height } = this.getElementSize(); // Destructuring assigment: http://es6-features.org/#ObjectMatchingShorthandNotation + + const div = document.createElement("div"); + div.className = "analogic-clock"; + div.style.width = `${width}px`; + div.style.height = `${height}px`; + + // SVG container. + const svg = document.createElementNS(svgNS, "svg"); + // Auto resize SVG using the view box magic: https://css-tricks.com/scale-svg/ + svg.setAttribute("viewBox", "0 0 100 100"); + + // Clock face. + const clockFace = document.createElementNS(svgNS, "g"); + clockFace.setAttribute("class", "clockface"); + const clockFaceBackground = document.createElementNS(svgNS, "circle"); + clockFaceBackground.setAttribute("cx", "50"); + clockFaceBackground.setAttribute("cy", "50"); + clockFaceBackground.setAttribute("r", "48"); + clockFaceBackground.setAttribute("fill", colors.watchFace); + clockFaceBackground.setAttribute("stroke", colors.watchFaceBorder); + clockFaceBackground.setAttribute("stroke-width", "2"); + clockFaceBackground.setAttribute("stroke-linecap", "round"); + // Insert the clockface background into the clockface group. + clockFace.append(clockFaceBackground); + + // Timezone complication. + const city = this.getHumanTimezone(); + if (city.length > 0) { + const timezoneComplication = document.createElementNS(svgNS, "text"); + timezoneComplication.setAttribute("text-anchor", "middle"); + timezoneComplication.setAttribute("font-size", "8"); + timezoneComplication.setAttribute( + "transform", + "translate(30 50) rotate(90)" // Rotate to counter the clock rotation. + ); + timezoneComplication.setAttribute("fill", colors.mark); + timezoneComplication.textContent = city; + clockFace.append(timezoneComplication); + } + + // Marks group. + const marksGroup = document.createElementNS(svgNS, "g"); + marksGroup.setAttribute("class", "marks"); + // Build the 12 hours mark. + const mainMarkGroup = document.createElementNS(svgNS, "g"); + mainMarkGroup.setAttribute("class", "mark"); + mainMarkGroup.setAttribute("transform", "translate(50 50)"); + const mark1a = document.createElementNS(svgNS, "line"); + mark1a.setAttribute("x1", "36"); + mark1a.setAttribute("y1", "0"); + mark1a.setAttribute("x2", "46"); + mark1a.setAttribute("y2", "0"); + mark1a.setAttribute("stroke", colors.mark); + mark1a.setAttribute("stroke-width", "5"); + const mark1b = document.createElementNS(svgNS, "line"); + mark1b.setAttribute("x1", "36"); + mark1b.setAttribute("y1", "0"); + mark1b.setAttribute("x2", "46"); + mark1b.setAttribute("y2", "0"); + mark1b.setAttribute("stroke", colors.watchFace); + mark1b.setAttribute("stroke-width", "1"); + // Insert the 12 mark lines into their group. + mainMarkGroup.append(mark1a, mark1b); + // Insert the main mark into the marks group. + marksGroup.append(mainMarkGroup); + // Build the rest of the marks. + for (let i = 1; i < 60; i++) { + const mark = document.createElementNS(svgNS, "line"); + mark.setAttribute("y1", "0"); + mark.setAttribute("y2", "0"); + mark.setAttribute("stroke", colors.mark); + mark.setAttribute("transform", `translate(50 50) rotate(${i * 6})`); + + if (i % 5 === 0) { + mark.setAttribute("x1", "38"); + mark.setAttribute("x2", "46"); + mark.setAttribute("stroke-width", i % 15 === 0 ? "2" : "1"); + } else { + mark.setAttribute("x1", "42"); + mark.setAttribute("x2", "46"); + mark.setAttribute("stroke-width", "0.5"); + } + + // Insert the mark into the marks group. + marksGroup.append(mark); + } + + /* Clock hands */ + + // Hour hand. + const hourHand = document.createElementNS(svgNS, "g"); + hourHand.setAttribute("class", "hour-hand"); + hourHand.setAttribute("transform", "translate(50 50)"); + // This will go back and will act like a border. + const hourHandA = document.createElementNS(svgNS, "line"); + hourHandA.setAttribute("class", "hour-hand-a"); + hourHandA.setAttribute("x1", "0"); + hourHandA.setAttribute("y1", "0"); + hourHandA.setAttribute("x2", "30"); + hourHandA.setAttribute("y2", "0"); + hourHandA.setAttribute("stroke", colors.handLight); + hourHandA.setAttribute("stroke-width", "4"); + hourHandA.setAttribute("stroke-linecap", "round"); + // This will go in front of the previous line. + const hourHandB = document.createElementNS(svgNS, "line"); + hourHandB.setAttribute("class", "hour-hand-b"); + hourHandB.setAttribute("x1", "0"); + hourHandB.setAttribute("y1", "0"); + hourHandB.setAttribute("x2", "29.9"); + hourHandB.setAttribute("y2", "0"); + hourHandB.setAttribute("stroke", colors.handDark); + hourHandB.setAttribute("stroke-width", "3.1"); + hourHandB.setAttribute("stroke-linecap", "round"); + // Append the elements to finish the hour hand. + hourHand.append(hourHandA, hourHandB); + + // Minute hand. + const minuteHand = document.createElementNS(svgNS, "g"); + minuteHand.setAttribute("class", "minute-hand"); + minuteHand.setAttribute("transform", "translate(50 50)"); + // This will go back and will act like a border. + const minuteHandA = document.createElementNS(svgNS, "line"); + minuteHandA.setAttribute("class", "minute-hand-a"); + minuteHandA.setAttribute("x1", "0"); + minuteHandA.setAttribute("y1", "0"); + minuteHandA.setAttribute("x2", "40"); + minuteHandA.setAttribute("y2", "0"); + minuteHandA.setAttribute("stroke", colors.handLight); + minuteHandA.setAttribute("stroke-width", "2"); + minuteHandA.setAttribute("stroke-linecap", "round"); + // This will go in front of the previous line. + const minuteHandB = document.createElementNS(svgNS, "line"); + minuteHandB.setAttribute("class", "minute-hand-b"); + minuteHandB.setAttribute("x1", "0"); + minuteHandB.setAttribute("y1", "0"); + minuteHandB.setAttribute("x2", "39.9"); + minuteHandB.setAttribute("y2", "0"); + minuteHandB.setAttribute("stroke", colors.handDark); + minuteHandB.setAttribute("stroke-width", "1.5"); + minuteHandB.setAttribute("stroke-linecap", "round"); + const minuteHandPin = document.createElementNS(svgNS, "circle"); + minuteHandPin.setAttribute("r", "3"); + minuteHandPin.setAttribute("fill", colors.handDark); + // Append the elements to finish the minute hand. + minuteHand.append(minuteHandA, minuteHandB, minuteHandPin); + + // Second hand. + const secondHand = document.createElementNS(svgNS, "g"); + secondHand.setAttribute("class", "second-hand"); + secondHand.setAttribute("transform", "translate(50 50)"); + const secondHandBar = document.createElementNS(svgNS, "line"); + secondHandBar.setAttribute("x1", "0"); + secondHandBar.setAttribute("y1", "0"); + secondHandBar.setAttribute("x2", "46"); + secondHandBar.setAttribute("y2", "0"); + secondHandBar.setAttribute("stroke", colors.secondHand); + secondHandBar.setAttribute("stroke-width", "1"); + secondHandBar.setAttribute("stroke-linecap", "round"); + const secondHandPin = document.createElementNS(svgNS, "circle"); + secondHandPin.setAttribute("r", "2"); + secondHandPin.setAttribute("fill", colors.secondHand); + // Append the elements to finish the second hand. + secondHand.append(secondHandBar, secondHandPin); + + // Pin. + const pin = document.createElementNS(svgNS, "circle"); + pin.setAttribute("cx", "50"); + pin.setAttribute("cy", "50"); + pin.setAttribute("r", "0.3"); + pin.setAttribute("fill", colors.handDark); + + // Get the hand angles. + const date = this.getOriginDate(); + const seconds = date.getSeconds(); + const minutes = date.getMinutes(); + const hours = date.getHours(); + const secAngle = (360 / 60) * seconds; + const minuteAngle = (360 / 60) * minutes + (360 / 60) * (seconds / 60); + const hourAngle = (360 / 12) * hours + (360 / 12) * (minutes / 60); + // Set the clock time by moving the hands. + hourHand.setAttribute("transform", `translate(50 50) rotate(${hourAngle})`); + minuteHand.setAttribute( + "transform", + `translate(50 50) rotate(${minuteAngle})` + ); + secondHand.setAttribute( + "transform", + `translate(50 50) rotate(${secAngle})` + ); + + // Build the clock + svg.append(clockFace, marksGroup, hourHand, minuteHand, secondHand, pin); + // Rotate the clock to its normal position. + svg.setAttribute("transform", "rotate(-90)"); + + /* Add the animation declaration to the container. + * Since the animation keyframes need to know the + * start angle, this angle is dynamic (current time), + * and we can't edit keyframes through javascript + * safely and with backwards compatibility, we need + * to inject it. + */ + div.innerHTML = ` + + `; + // Add the clock to the container + div.append(svg); + + return div; + } + + /** + * Create a element which contains a representation of a digital clock. + * @return DOM Element. + */ + private createDigitalClock(): HTMLElement { + const element: HTMLDivElement = document.createElement("div"); + element.className = "digital-clock"; + + const { width } = this.getElementSize(); // Destructuring assigment: http://es6-features.org/#ObjectMatchingShorthandNotation + + // Calculate font size to adapt the font to the item size. + const baseTimeFontSize = 20; // Per 100px of width. + const dateFontSizeMultiplier = 0.5; + const tzFontSizeMultiplier = 6 / this.props.clockTimezone.length; + const timeFontSize = (baseTimeFontSize * width) / 100; + const dateFontSize = + (baseTimeFontSize * dateFontSizeMultiplier * width) / 100; + const tzFontSize = Math.min( + (baseTimeFontSize * tzFontSizeMultiplier * width) / 100, + (width / 100) * 10 + ); + + // Date calculated using the original timezone. + const date = this.getOriginDate(); + + // Date. + if (this.props.clockFormat === "datetime") { + const dateElem: HTMLSpanElement = document.createElement("span"); + dateElem.className = "date"; + dateElem.textContent = humanDate(date, "default"); + dateElem.style.fontSize = `${dateFontSize}px`; + if (this.props.color) dateElem.style.color = this.props.color; + element.append(dateElem); + } + + // Time. + const timeElem: HTMLSpanElement = document.createElement("span"); + timeElem.className = "time"; + timeElem.textContent = humanTime(date); + timeElem.style.fontSize = `${timeFontSize}px`; + if (this.props.color) timeElem.style.color = this.props.color; + element.append(timeElem); + + // City name. + const city = this.getHumanTimezone(); + if (city.length > 0) { + const tzElem: HTMLSpanElement = document.createElement("span"); + tzElem.className = "timezone"; + tzElem.textContent = city; + tzElem.style.fontSize = `${tzFontSize}px`; + if (this.props.color) tzElem.style.color = this.props.color; + element.append(tzElem); + } + + return element; + } + + /** + * Generate the current date using the timezone offset stored into the properties. + * @return The current date. + */ + private getOriginDate(initialDate: Date | null = null): Date { + const d = initialDate ? initialDate : new Date(); + const targetTZOffset = this.props.clockTimezoneOffset * 1000; // In ms. + const localTZOffset = d.getTimezoneOffset() * 60 * 1000; // In ms. + const utimestamp = d.getTime() + targetTZOffset + localTZOffset; + + return new Date(utimestamp); + } + + /** + * Extract a human readable city name from the timezone text. + * @param timezone Timezone text. + */ + public getHumanTimezone(timezone: string = this.props.clockTimezone): string { + const [, city = ""] = timezone.split("/"); + return city.replace("_", " "); + } + + /** + * Generate a element size using the current size and the default values. + * @return The size. + */ + private getElementSize( + width: number = this.props.width, + height: number = this.props.height + ): Size { + switch (this.props.clockType) { + case "analogic": { + let diameter = 100; // Default value. + + if (width > 0 && height > 0) { + diameter = Math.min(width, height); + } else if (width > 0) { + diameter = width; + } else if (height > 0) { + diameter = height; + } + + return { + width: diameter, + height: diameter + }; + } + case "digital": { + if (width > 0 && height > 0) { + // The proportion of the clock should be (width = height / 2) aproximately. + height = width / 2 < height ? width / 2 : height; + } else if (width > 0) { + height = width / 2; + } else if (height > 0) { + // The proportion of the clock should be (height * 2 = width) aproximately. + width = height * 2; + } else { + width = 100; // Default value. + height = 50; // Default value. + } + + return { + width, + height + }; + } + default: + throw new Error("invalid clock type."); + } + } +} diff --git a/visual_console_client/src/items/Clock/spec.ts b/visual_console_client/src/items/Clock/spec.ts new file mode 100644 index 0000000000..7380f98468 --- /dev/null +++ b/visual_console_client/src/items/Clock/spec.ts @@ -0,0 +1,67 @@ +import Clock, { clockPropsDecoder } from "."; + +const genericRawProps = { + id: 1, + type: 19, // Clock item = 19 + label: null, + isLinkEnabled: false, + isOnTop: false, + parentId: null, + aclGroupId: null +}; + +const positionRawProps = { + x: 100, + y: 50 +}; + +const sizeRawProps = { + width: 100, + height: 100 +}; + +const digitalClockProps = { + clockType: "digital", + clockFormat: "datetime", + clockTimezone: "Madrid", + clockTimezoneOffset: 60, + showClockTimezone: true, + color: "white" +}; + +const linkedModuleProps = { + // Agent props. + agentId: null, + agentName: null, + // Module props. + moduleId: null, + moduleName: null +}; + +describe("Clock item", () => { + const clockInstance = new Clock( + clockPropsDecoder({ + ...genericRawProps, + ...positionRawProps, + ...sizeRawProps, + ...linkedModuleProps, + ...digitalClockProps + }) + ); + + it("should have the digital-clock class", () => { + expect( + clockInstance.elementRef.getElementsByClassName("digital-clock").length + ).toBeGreaterThan(0); + }); + + describe("getHumanTimezone function", () => { + it("should return a better timezone", () => { + expect(clockInstance.getHumanTimezone("America/New_York")).toBe( + "New York" + ); + expect(clockInstance.getHumanTimezone("Europe/Madrid")).toBe("Madrid"); + expect(clockInstance.getHumanTimezone("Asia/Tokyo")).toBe("Tokyo"); + }); + }); +}); diff --git a/visual_console_client/src/items/Clock/styles.css b/visual_console_client/src/items/Clock/styles.css new file mode 100644 index 0000000000..cfa6f11eb5 --- /dev/null +++ b/visual_console_client/src/items/Clock/styles.css @@ -0,0 +1,48 @@ +@font-face { + font-family: Alarm Clock; + src: url(./alarm-clock.ttf); +} + +/* Digital clock */ + +.visual-console-item .digital-clock { + display: flex; + flex-direction: column; + justify-content: center; + justify-items: center; + align-content: center; + align-items: center; +} + +.visual-console-item .digital-clock > span { + font-family: "Alarm Clock", "Courier New", Courier, monospace; + font-size: 50px; + + /* To improve legibility */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; + text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px; +} + +.visual-console-item .digital-clock > span.date { + font-size: 25px; +} + +.visual-console-item .digital-clock > span.timezone { + font-size: 25px; +} + +/* Analog clock */ + +.visual-console-item .analogic-clock .hour-hand { + animation: rotate-hour 43200s infinite linear; +} + +.visual-console-item .analogic-clock .minute-hand { + animation: rotate-minute 3600s infinite linear; +} + +.visual-console-item .analogic-clock .second-hand { + animation: rotate-second 60s infinite linear; +} diff --git a/visual_console_client/src/items/ColorCloud.spec.ts b/visual_console_client/src/items/ColorCloud.spec.ts new file mode 100644 index 0000000000..103850b04b --- /dev/null +++ b/visual_console_client/src/items/ColorCloud.spec.ts @@ -0,0 +1,64 @@ +import ColorCloud, { colorCloudPropsDecoder } from "./ColorCloud"; + +const genericRawProps = { + id: 1, + type: 20, // COlor cloud item = 20 + label: null, + isLinkEnabled: false, + isOnTop: false, + parentId: null, + aclGroupId: null +}; + +const positionRawProps = { + x: 100, + y: 50 +}; + +const sizeRawProps = { + width: 100, + height: 100 +}; + +const colorCloudProps = { + color: "rgb(100, 50, 245)" +}; + +const linkedModuleProps = { + // Agent props. + agentId: null, + agentName: null, + // Module props. + moduleId: null, + moduleName: null +}; + +describe("Color cloud item", () => { + const colorCloudInstance = new ColorCloud( + colorCloudPropsDecoder({ + ...genericRawProps, + ...positionRawProps, + ...sizeRawProps, + ...linkedModuleProps, + ...colorCloudProps + }) + ); + + it("should throw when using an invalid color into the props decoder", () => { + expect(() => + colorCloudPropsDecoder({ + ...genericRawProps, + ...positionRawProps, + ...sizeRawProps, + ...linkedModuleProps, + color: null + }) + ).toThrowError(TypeError); + }); + + it("should have the color-cloud class", () => { + expect( + colorCloudInstance.elementRef.getElementsByClassName("color-cloud").length + ).toBeGreaterThan(0); + }); +}); diff --git a/visual_console_client/src/items/ColorCloud.ts b/visual_console_client/src/items/ColorCloud.ts new file mode 100644 index 0000000000..0b5dfe9948 --- /dev/null +++ b/visual_console_client/src/items/ColorCloud.ts @@ -0,0 +1,100 @@ +import { + WithModuleProps, + LinkedVisualConsoleProps, + UnknownObject +} from "../types"; +import { modulePropsDecoder, linkedVCPropsDecoder } from "../lib"; +import Item, { itemBasePropsDecoder, ItemType, ItemProps } from "../Item"; + +export type ColorCloudProps = { + type: ItemType.COLOR_CLOUD; + color: string; + // TODO: Add the rest of the color cloud values? +} & ItemProps & + WithModuleProps & + LinkedVisualConsoleProps; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the static graph props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function colorCloudPropsDecoder( + data: UnknownObject +): ColorCloudProps | never { + // TODO: Validate the color. + if (typeof data.color !== "string" || data.color.length === 0) { + throw new TypeError("invalid color."); + } + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.COLOR_CLOUD, + color: data.color, + ...modulePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + ...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +const svgNS = "http://www.w3.org/2000/svg"; + +export default class ColorCloud extends Item { + protected createDomElement(): HTMLElement { + const container: HTMLDivElement = document.createElement("div"); + container.className = "color-cloud"; + + // Add the SVG. + container.append(this.createSvgElement()); + + return container; + } + + public createSvgElement(): SVGSVGElement { + const gradientId = `grad_${this.props.id}`; + // SVG container. + const svg = document.createElementNS(svgNS, "svg"); + // Auto resize SVG using the view box magic: https://css-tricks.com/scale-svg/ + svg.setAttribute("viewBox", "0 0 100 100"); + + // Defs. + const defs = document.createElementNS(svgNS, "defs"); + // Radial gradient. + const radialGradient = document.createElementNS(svgNS, "radialGradient"); + radialGradient.setAttribute("id", gradientId); + radialGradient.setAttribute("cx", "50%"); + radialGradient.setAttribute("cy", "50%"); + radialGradient.setAttribute("r", "50%"); + radialGradient.setAttribute("fx", "50%"); + radialGradient.setAttribute("fy", "50%"); + // Stops. + const stop0 = document.createElementNS(svgNS, "stop"); + stop0.setAttribute("offset", "0%"); + stop0.setAttribute( + "style", + `stop-color:${this.props.color};stop-opacity:0.9` + ); + const stop100 = document.createElementNS(svgNS, "stop"); + stop100.setAttribute("offset", "100%"); + stop100.setAttribute( + "style", + `stop-color:${this.props.color};stop-opacity:0` + ); + // Circle. + const circle = document.createElementNS(svgNS, "circle"); + circle.setAttribute("fill", `url(#${gradientId})`); + circle.setAttribute("cx", "50%"); + circle.setAttribute("cy", "50%"); + circle.setAttribute("r", "50%"); + + // Append elements. + radialGradient.append(stop0, stop100); + defs.append(radialGradient); + svg.append(defs, circle); + + return svg; + } +} diff --git a/visual_console_client/src/items/DonutGraph.ts b/visual_console_client/src/items/DonutGraph.ts new file mode 100644 index 0000000000..d60f268567 --- /dev/null +++ b/visual_console_client/src/items/DonutGraph.ts @@ -0,0 +1,78 @@ +import { + LinkedVisualConsoleProps, + UnknownObject, + WithModuleProps +} from "../types"; +import { + linkedVCPropsDecoder, + modulePropsDecoder, + decodeBase64, + stringIsEmpty +} from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +export type DonutGraphProps = { + type: ItemType.DONUT_GRAPH; + html: string; +} & ItemProps & + WithModuleProps & + LinkedVisualConsoleProps; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the donut graph props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function donutGraphPropsDecoder( + data: UnknownObject +): DonutGraphProps | never { + if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) { + throw new TypeError("missing html content."); + } + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.DONUT_GRAPH, + html: !stringIsEmpty(data.html) + ? data.html + : decodeBase64(data.encodedHtml), + ...modulePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + ...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +export default class DonutGraph extends Item { + protected createDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "donut-graph"; + element.innerHTML = this.props.html; + + // Hack to execute the JS after the HTML is added to the DOM. + const scripts = element.getElementsByTagName("script"); + for (let i = 0; i < scripts.length; i++) { + setTimeout(() => { + if (scripts[i].src.length === 0) eval(scripts[i].innerHTML.trim()); + }, 0); + } + + return element; + } + + protected updateDomElement(element: HTMLElement): void { + element.innerHTML = this.props.html; + + // Hack to execute the JS after the HTML is added to the DOM. + const aux = document.createElement("div"); + aux.innerHTML = this.props.html; + const scripts = aux.getElementsByTagName("script"); + for (let i = 0; i < scripts.length; i++) { + if (scripts[i].src.length === 0) { + eval(scripts[i].innerHTML.trim()); + } + } + } +} diff --git a/visual_console_client/src/items/EventsHistory.ts b/visual_console_client/src/items/EventsHistory.ts new file mode 100644 index 0000000000..7e9db0ae9b --- /dev/null +++ b/visual_console_client/src/items/EventsHistory.ts @@ -0,0 +1,78 @@ +import { UnknownObject, WithModuleProps } from "../types"; +import { + modulePropsDecoder, + parseIntOr, + decodeBase64, + stringIsEmpty +} from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +export type EventsHistoryProps = { + type: ItemType.AUTO_SLA_GRAPH; + maxTime: number | null; + html: string; +} & ItemProps & + WithModuleProps; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the events history props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function eventsHistoryPropsDecoder( + data: UnknownObject +): EventsHistoryProps | never { + if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) { + throw new TypeError("missing html content."); + } + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.AUTO_SLA_GRAPH, + maxTime: parseIntOr(data.maxTime, null), + html: !stringIsEmpty(data.html) + ? data.html + : decodeBase64(data.encodedHtml), + ...modulePropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +export default class EventsHistory extends Item { + protected createDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "events-history"; + element.innerHTML = this.props.html; + + // Hack to execute the JS after the HTML is added to the DOM. + const scripts = element.getElementsByTagName("script"); + for (let i = 0; i < scripts.length; i++) { + if (scripts[i].src.length === 0) { + setTimeout(() => { + try { + eval(scripts[i].innerHTML.trim()); + } catch (ignored) {} // eslint-disable-line no-empty + }, 0); + } + } + + return element; + } + + protected updateDomElement(element: HTMLElement): void { + element.innerHTML = this.props.html; + + // Hack to execute the JS after the HTML is added to the DOM. + const aux = document.createElement("div"); + aux.innerHTML = this.props.html; + const scripts = aux.getElementsByTagName("script"); + for (let i = 0; i < scripts.length; i++) { + if (scripts[i].src.length === 0) { + eval(scripts[i].innerHTML.trim()); + } + } + } +} diff --git a/visual_console_client/src/items/Group.spec.ts b/visual_console_client/src/items/Group.spec.ts new file mode 100644 index 0000000000..e00a5cf327 --- /dev/null +++ b/visual_console_client/src/items/Group.spec.ts @@ -0,0 +1,44 @@ +import Group, { groupPropsDecoder } from "./Group"; + +const genericRawProps = { + id: 1, + type: 11, // Group item = 11 + label: null, + isLinkEnabled: false, + isOnTop: false, + parentId: null, + aclGroupId: null +}; + +const positionRawProps = { + x: 100, + y: 50 +}; + +const sizeRawProps = { + width: 100, + height: 100 +}; + +const groupRawProps = { + imageSrc: + "https://brutus.artica.lan:8081/uploads/-/system/project/avatar/1/1.png", + groupId: 1 +}; + +describe("Group item", () => { + const groupInstance = new Group( + groupPropsDecoder({ + ...genericRawProps, + ...positionRawProps, + ...sizeRawProps, + ...groupRawProps + }) + ); + + it("should have the group class", () => { + expect( + groupInstance.elementRef.getElementsByClassName("group").length + ).toBeGreaterThan(0); + }); +}); diff --git a/visual_console_client/src/items/Group.ts b/visual_console_client/src/items/Group.ts new file mode 100644 index 0000000000..fa97f69a62 --- /dev/null +++ b/visual_console_client/src/items/Group.ts @@ -0,0 +1,80 @@ +import { LinkedVisualConsoleProps, UnknownObject } from "../types"; +import { + linkedVCPropsDecoder, + parseIntOr, + notEmptyStringOr, + stringIsEmpty, + decodeBase64, + parseBoolean +} from "../lib"; +import Item, { ItemProps, itemBasePropsDecoder, ItemType } from "../Item"; + +export type GroupProps = { + type: ItemType.GROUP_ITEM; + groupId: number; + imageSrc: string | null; // URL? + statusImageSrc: string | null; + showStatistics: boolean; + html?: string | null; +} & ItemProps & + LinkedVisualConsoleProps; + +function extractHtml(data: UnknownObject): string | null { + if (!stringIsEmpty(data.html)) return data.html; + if (!stringIsEmpty(data.encodedHtml)) return decodeBase64(data.encodedHtml); + return null; +} + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the group props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function groupPropsDecoder(data: UnknownObject): GroupProps | never { + if ( + (typeof data.imageSrc !== "string" || data.imageSrc.length === 0) && + data.encodedHtml === null + ) { + throw new TypeError("invalid image src."); + } + if (parseIntOr(data.groupId, null) === null) { + throw new TypeError("invalid group Id."); + } + + const showStatistics = parseBoolean(data.showStatistics); + const html = showStatistics ? extractHtml(data) : null; + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.GROUP_ITEM, + groupId: parseInt(data.groupId), + imageSrc: notEmptyStringOr(data.imageSrc, null), + statusImageSrc: notEmptyStringOr(data.statusImageSrc, null), + showStatistics, + html, + ...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +export default class Group extends Item { + protected createDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "group"; + + if (!this.props.showStatistics && this.props.statusImageSrc !== null) { + // Icon with status. + element.style.background = `url(${this.props.statusImageSrc}) no-repeat`; + element.style.backgroundSize = "contain"; + element.style.backgroundPosition = "center"; + } else if (this.props.showStatistics && this.props.html != null) { + // Stats table. + element.innerHTML = this.props.html; + } + + return element; + } +} diff --git a/visual_console_client/src/items/Icon.ts b/visual_console_client/src/items/Icon.ts new file mode 100644 index 0000000000..12c1b035c7 --- /dev/null +++ b/visual_console_client/src/items/Icon.ts @@ -0,0 +1,43 @@ +import { LinkedVisualConsoleProps, UnknownObject } from "../types"; +import { linkedVCPropsDecoder } from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +export type IconProps = { + type: ItemType.ICON; + imageSrc: string; // URL? +} & ItemProps & + LinkedVisualConsoleProps; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the icon props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function iconPropsDecoder(data: UnknownObject): IconProps | never { + if (typeof data.imageSrc !== "string" || data.imageSrc.length === 0) { + throw new TypeError("invalid image src."); + } + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.ICON, + imageSrc: data.imageSrc, + ...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +export default class Icon extends Item { + protected createDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "icon"; + element.style.background = `url(${this.props.imageSrc}) no-repeat`; + element.style.backgroundSize = "contain"; + element.style.backgroundPosition = "center"; + + return element; + } +} diff --git a/visual_console_client/src/items/Label.ts b/visual_console_client/src/items/Label.ts new file mode 100644 index 0000000000..c8de572c15 --- /dev/null +++ b/visual_console_client/src/items/Label.ts @@ -0,0 +1,47 @@ +import { LinkedVisualConsoleProps, UnknownObject } from "../types"; +import { linkedVCPropsDecoder } from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +export type LabelProps = { + type: ItemType.LABEL; +} & ItemProps & + LinkedVisualConsoleProps; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the label props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function labelPropsDecoder(data: UnknownObject): LabelProps | never { + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.LABEL, + ...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +export default class Label extends Item { + protected createDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "label"; + element.innerHTML = this.getLabelWithMacrosReplaced(); + + return element; + } + + /** + * @override Item.createLabelDomElement + * Create a new label for the visual console item. + * @return Item label. + */ + public createLabelDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "visual-console-item-label"; + // Always return an empty label. + return element; + } +} diff --git a/visual_console_client/src/items/Line.ts b/visual_console_client/src/items/Line.ts new file mode 100644 index 0000000000..20532e44ea --- /dev/null +++ b/visual_console_client/src/items/Line.ts @@ -0,0 +1,147 @@ +import { UnknownObject, Position, Size } from "../types"; +import { parseIntOr, notEmptyStringOr } from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +interface LineProps extends ItemProps { + // Overrided properties. + readonly type: ItemType.LINE_ITEM; + label: null; + isLinkEnabled: false; + parentId: null; + aclGroupId: null; + // Custom properties. + startPosition: Position; + endPosition: Position; + lineWidth: number; + color: string | null; +} + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the item props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function linePropsDecoder(data: UnknownObject): LineProps | never { + const props: LineProps = { + ...itemBasePropsDecoder({ ...data, width: 1, height: 1 }), // Object spread. It will merge the properties of the two objects. + type: ItemType.LINE_ITEM, + label: null, + isLinkEnabled: false, + parentId: null, + aclGroupId: null, + // Initialize Position & Size. + x: 0, + y: 0, + width: 0, + height: 0, + // Custom properties. + startPosition: { + x: parseIntOr(data.startX, 0), + y: parseIntOr(data.startY, 0) + }, + endPosition: { + x: parseIntOr(data.endX, 0), + y: parseIntOr(data.endY, 0) + }, + lineWidth: parseIntOr(data.lineWidth || data.borderWidth, 1), + color: notEmptyStringOr(data.borderColor || data.color, null) + }; + + /* + * We need to enhance the props with the extracted size and position + * of the box cause there are missing at the props update. A better + * solution would be overriding the props setter to do it there, but + * the language doesn't allow it while targetting ES5. + * TODO: We need to figure out a more consistent solution. + */ + + return { + ...props, + // Enhance the props extracting the box size and position. + // eslint-disable-next-line @typescript-eslint/no-use-before-define + ...Line.extractBoxSizeAndPosition(props) + }; +} + +export default class Line extends Item { + /** + * @override + */ + public constructor(props: LineProps) { + /* + * We need to override the constructor cause we need to obtain + * the + * box size and position from the start and finish points + * of the line. + */ + super({ + ...props, + ...Line.extractBoxSizeAndPosition(props) + }); + } + + /** + * @override + * To create the item's DOM representation. + * @return Item. + */ + protected createDomElement(): HTMLElement { + const element: HTMLDivElement = document.createElement("div"); + element.className = "line"; + + const svgNS = "http://www.w3.org/2000/svg"; + // SVG container. + const svg = document.createElementNS(svgNS, "svg"); + // Set SVG size. + svg.setAttribute( + "width", + (this.props.width + this.props.lineWidth).toString() + ); + svg.setAttribute( + "height", + (this.props.height + this.props.lineWidth).toString() + ); + const line = document.createElementNS(svgNS, "line"); + line.setAttribute( + "x1", + `${this.props.startPosition.x - this.props.x + this.props.lineWidth / 2}` + ); + line.setAttribute( + "y1", + `${this.props.startPosition.y - this.props.y + this.props.lineWidth / 2}` + ); + line.setAttribute( + "x2", + `${this.props.endPosition.x - this.props.x + this.props.lineWidth / 2}` + ); + line.setAttribute( + "y2", + `${this.props.endPosition.y - this.props.y + this.props.lineWidth / 2}` + ); + line.setAttribute("stroke", this.props.color || "black"); + line.setAttribute("stroke-width", this.props.lineWidth.toString()); + + svg.append(line); + element.append(svg); + + return element; + } + + /** + * Extract the size and position of the box from + * the start and the finish of the line. + * @param props Item properties. + */ + public static extractBoxSizeAndPosition(props: LineProps): Size & Position { + return { + width: Math.abs(props.startPosition.x - props.endPosition.x), + height: Math.abs(props.startPosition.y - props.endPosition.y), + x: Math.min(props.startPosition.x, props.endPosition.x), + y: Math.min(props.startPosition.y, props.endPosition.y) + }; + } +} diff --git a/visual_console_client/src/items/ModuleGraph.ts b/visual_console_client/src/items/ModuleGraph.ts new file mode 100644 index 0000000000..3440496d19 --- /dev/null +++ b/visual_console_client/src/items/ModuleGraph.ts @@ -0,0 +1,118 @@ +import { + LinkedVisualConsoleProps, + UnknownObject, + WithModuleProps +} from "../types"; +import { + linkedVCPropsDecoder, + modulePropsDecoder, + decodeBase64, + stringIsEmpty +} from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +export type ModuleGraphProps = { + type: ItemType.MODULE_GRAPH; + html: string; +} & ItemProps & + WithModuleProps & + LinkedVisualConsoleProps; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the module graph props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function moduleGraphPropsDecoder( + data: UnknownObject +): ModuleGraphProps | never { + if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) { + throw new TypeError("missing html content."); + } + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.MODULE_GRAPH, + html: !stringIsEmpty(data.html) + ? data.html + : decodeBase64(data.encodedHtml), + ...modulePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + ...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +export default class ModuleGraph extends Item { + /** + * @override Item.resizeElement. + * Resize the DOM content container. + * We need to override the resize function cause this item's height + * is larger than the configured and the graph is over the label. + * @param width + * @param height + */ + protected resizeElement(width: number): void { + super.resizeElement(width, 0); + } + + protected createDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "module-graph"; + element.innerHTML = this.props.html; + + // Remove the overview graph. + const legendP = element.getElementsByTagName("p"); + for (let i = 0; i < legendP.length; i++) { + legendP[i].style.margin = "0px"; + } + + // Remove the overview graph. + const overviewGraphs = element.getElementsByClassName("overview_graph"); + for (let i = 0; i < overviewGraphs.length; i++) { + overviewGraphs[i].remove(); + } + + // Hack to execute the JS after the HTML is added to the DOM. + const scripts = element.getElementsByTagName("script"); + for (let i = 0; i < scripts.length; i++) { + if (scripts[i].src.length === 0) { + setTimeout(() => { + try { + eval(scripts[i].innerHTML.trim()); + } catch (ignored) {} // eslint-disable-line no-empty + }, 0); + } + } + + return element; + } + + protected updateDomElement(element: HTMLElement): void { + element.innerHTML = this.props.html; + + // Remove the overview graph. + const legendP = element.getElementsByTagName("p"); + for (let i = 0; i < legendP.length; i++) { + legendP[i].style.margin = "0px"; + } + + // Remove the overview graph. + const overviewGraphs = element.getElementsByClassName("overview_graph"); + for (let i = 0; i < overviewGraphs.length; i++) { + overviewGraphs[i].remove(); + } + + // Hack to execute the JS after the HTML is added to the DOM. + const aux = document.createElement("div"); + aux.innerHTML = this.props.html; + const scripts = aux.getElementsByTagName("script"); + for (let i = 0; i < scripts.length; i++) { + if (scripts[i].src.length === 0) { + eval(scripts[i].innerHTML.trim()); + } + } + } +} diff --git a/visual_console_client/src/items/Percentile.ts b/visual_console_client/src/items/Percentile.ts new file mode 100644 index 0000000000..d4dec30d59 --- /dev/null +++ b/visual_console_client/src/items/Percentile.ts @@ -0,0 +1,260 @@ +import { arc as arcFactory } from "d3-shape"; + +import { + LinkedVisualConsoleProps, + UnknownObject, + WithModuleProps +} from "../types"; +import { + linkedVCPropsDecoder, + modulePropsDecoder, + notEmptyStringOr, + parseIntOr, + parseFloatOr +} from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +export type PercentileProps = { + type: ItemType.PERCENTILE_BAR; + percentileType: + | "progress-bar" + | "bubble" + | "circular-progress-bar" + | "circular-progress-bar-alt"; + valueType: "percent" | "value"; + minValue: number | null; + maxValue: number | null; + color: string | null; + labelColor: string | null; + value: number | null; + unit: string | null; +} & ItemProps & + WithModuleProps & + LinkedVisualConsoleProps; + +/** + * Extract a valid enum value from a raw type value. + * @param type Raw value. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function extractPercentileType(type: any): PercentileProps["percentileType"] { + switch (type) { + case "progress-bar": + case "bubble": + case "circular-progress-bar": + case "circular-progress-bar-alt": + return type; + default: + case ItemType.PERCENTILE_BAR: + return "progress-bar"; + case ItemType.PERCENTILE_BUBBLE: + return "bubble"; + case ItemType.CIRCULAR_PROGRESS_BAR: + return "circular-progress-bar"; + case ItemType.CIRCULAR_INTERIOR_PROGRESS_BAR: + return "circular-progress-bar-alt"; + } +} + +/** + * Extract a valid enum value from a raw value type value. + * @param type Raw value. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function extractValueType(valueType: any): PercentileProps["valueType"] { + switch (valueType) { + case "percent": + case "value": + return valueType; + default: + return "percent"; + } +} + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the percentile props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function percentilePropsDecoder( + data: UnknownObject +): PercentileProps | never { + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.PERCENTILE_BAR, + percentileType: extractPercentileType(data.percentileType || data.type), + valueType: extractValueType(data.valueType), + minValue: parseIntOr(data.minValue, null), + maxValue: parseIntOr(data.maxValue, null), + color: notEmptyStringOr(data.color, null), + labelColor: notEmptyStringOr(data.labelColor, null), + value: parseFloatOr(data.value, null), + unit: notEmptyStringOr(data.unit, null), + ...modulePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + ...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +const svgNS = "http://www.w3.org/2000/svg"; + +export default class Percentile extends Item { + protected createDomElement(): HTMLElement { + const colors = { + background: "#000000", + progress: this.props.color || "#F0F0F0", + text: this.props.labelColor || "#444444" + }; + // Progress. + const progress = this.getProgress(); + // Main element. + const element = document.createElement("div"); + // SVG container. + const svg = document.createElementNS(svgNS, "svg"); + + switch (this.props.percentileType) { + case "progress-bar": + { + const backgroundRect = document.createElementNS(svgNS, "rect"); + backgroundRect.setAttribute("fill", colors.background); + backgroundRect.setAttribute("fill-opacity", "0.5"); + backgroundRect.setAttribute("width", "100"); + backgroundRect.setAttribute("height", "20"); + backgroundRect.setAttribute("rx", "5"); + backgroundRect.setAttribute("ry", "5"); + const progressRect = document.createElementNS(svgNS, "rect"); + progressRect.setAttribute("fill", colors.progress); + progressRect.setAttribute("fill-opacity", "1"); + progressRect.setAttribute("width", `${progress}`); + progressRect.setAttribute("height", "20"); + progressRect.setAttribute("rx", "5"); + progressRect.setAttribute("ry", "5"); + const text = document.createElementNS(svgNS, "text"); + text.setAttribute("text-anchor", "middle"); + text.setAttribute("alignment-baseline", "middle"); + text.setAttribute("font-size", "12"); + text.setAttribute("font-family", "arial"); + text.setAttribute("font-weight", "bold"); + text.setAttribute("transform", "translate(50 11)"); + text.setAttribute("fill", colors.text); + + if (this.props.valueType === "value") { + text.textContent = this.props.unit + ? `${this.props.value} ${this.props.unit}` + : `${this.props.value}`; + } else { + text.textContent = `${progress}%`; + } + + // Auto resize SVG using the view box magic: https://css-tricks.com/scale-svg/ + svg.setAttribute("viewBox", "0 0 100 20"); + svg.append(backgroundRect, progressRect, text); + } + break; + case "bubble": + case "circular-progress-bar": + case "circular-progress-bar-alt": + { + // Auto resize SVG using the view box magic: https://css-tricks.com/scale-svg/ + svg.setAttribute("viewBox", "0 0 100 100"); + + if (this.props.percentileType === "bubble") { + // Create and append the circles. + const backgroundCircle = document.createElementNS(svgNS, "circle"); + backgroundCircle.setAttribute("transform", "translate(50 50)"); + backgroundCircle.setAttribute("fill", colors.background); + backgroundCircle.setAttribute("fill-opacity", "0.5"); + backgroundCircle.setAttribute("r", "50"); + const progressCircle = document.createElementNS(svgNS, "circle"); + progressCircle.setAttribute("transform", "translate(50 50)"); + progressCircle.setAttribute("fill", colors.progress); + progressCircle.setAttribute("fill-opacity", "1"); + progressCircle.setAttribute("r", `${progress / 2}`); + + svg.append(backgroundCircle, progressCircle); + } else { + // Create and append the circles. + const arcProps = { + innerRadius: + this.props.percentileType === "circular-progress-bar" ? 30 : 0, + outerRadius: 50, + startAngle: 0, + endAngle: Math.PI * 2 + }; + const arc = arcFactory(); + + const backgroundCircle = document.createElementNS(svgNS, "path"); + backgroundCircle.setAttribute("transform", "translate(50 50)"); + backgroundCircle.setAttribute("fill", colors.background); + backgroundCircle.setAttribute("fill-opacity", "0.5"); + backgroundCircle.setAttribute("d", `${arc(arcProps)}`); + const progressCircle = document.createElementNS(svgNS, "path"); + progressCircle.setAttribute("transform", "translate(50 50)"); + progressCircle.setAttribute("fill", colors.progress); + progressCircle.setAttribute("fill-opacity", "1"); + progressCircle.setAttribute( + "d", + `${arc({ + ...arcProps, + endAngle: arcProps.endAngle * (progress / 100) + })}` + ); + + svg.append(backgroundCircle, progressCircle); + } + + // Create and append the text. + const text = document.createElementNS(svgNS, "text"); + text.setAttribute("text-anchor", "middle"); + text.setAttribute("alignment-baseline", "middle"); + text.setAttribute("font-size", "16"); + text.setAttribute("font-family", "arial"); + text.setAttribute("font-weight", "bold"); + text.setAttribute("fill", colors.text); + + if (this.props.valueType === "value") { + // Show value and unit in 1 (no unit) or 2 lines. + if (this.props.unit && this.props.unit.length > 0) { + const value = document.createElementNS(svgNS, "tspan"); + value.setAttribute("x", "0"); + value.setAttribute("dy", "1em"); + value.textContent = `${this.props.value}`; + const unit = document.createElementNS(svgNS, "tspan"); + unit.setAttribute("x", "0"); + unit.setAttribute("dy", "1em"); + unit.textContent = `${this.props.unit}`; + text.append(value, unit); + text.setAttribute("transform", "translate(50 33)"); + } else { + text.textContent = `${this.props.value}`; + text.setAttribute("transform", "translate(50 50)"); + } + } else { + // Percentage. + text.textContent = `${progress}%`; + text.setAttribute("transform", "translate(50 50)"); + } + + svg.append(text); + } + break; + } + + element.append(svg); + + return element; + } + + private getProgress(): number { + const minValue = this.props.minValue || 0; + const maxValue = this.props.maxValue || 100; + const value = this.props.value == null ? 0 : this.props.value; + + if (value <= minValue) return 0; + else if (value >= maxValue) return 100; + else return Math.trunc(((value - minValue) / (maxValue - minValue)) * 100); + } +} diff --git a/visual_console_client/src/items/Service.ts b/visual_console_client/src/items/Service.ts new file mode 100644 index 0000000000..9440503e80 --- /dev/null +++ b/visual_console_client/src/items/Service.ts @@ -0,0 +1,70 @@ +import { UnknownObject } from "../types"; +import { + stringIsEmpty, + notEmptyStringOr, + decodeBase64, + parseIntOr +} from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +export type ServiceProps = { + type: ItemType.SERVICE; + serviceId: number; + imageSrc: string | null; + statusImageSrc: string | null; + encodedTitle: string | null; +} & ItemProps; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the service props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function servicePropsDecoder(data: UnknownObject): ServiceProps | never { + if (data.imageSrc !== null) { + if ( + typeof data.statusImageSrc !== "string" || + data.imageSrc.statusImageSrc === 0 + ) { + throw new TypeError("invalid status image src."); + } + } else { + if (stringIsEmpty(data.encodedTitle)) { + throw new TypeError("missing encode tittle content."); + } + } + + if (parseIntOr(data.serviceId, null) === null) { + throw new TypeError("invalid service id."); + } + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.SERVICE, + serviceId: data.serviceId, + imageSrc: notEmptyStringOr(data.imageSrc, null), + statusImageSrc: notEmptyStringOr(data.statusImageSrc, null), + encodedTitle: notEmptyStringOr(data.encodedTitle, null) + }; +} + +export default class Service extends Item { + public createDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "service"; + + if (this.props.statusImageSrc !== null) { + element.style.background = `url(${this.props.statusImageSrc}) no-repeat`; + element.style.backgroundSize = "contain"; + element.style.backgroundPosition = "center"; + } else if (this.props.encodedTitle !== null) { + element.innerHTML = decodeBase64(this.props.encodedTitle); + } + + return element; + } +} diff --git a/visual_console_client/src/items/SimpleValue.ts b/visual_console_client/src/items/SimpleValue.ts new file mode 100644 index 0000000000..8464881a61 --- /dev/null +++ b/visual_console_client/src/items/SimpleValue.ts @@ -0,0 +1,129 @@ +import { + LinkedVisualConsoleProps, + UnknownObject, + WithModuleProps +} from "../types"; +import { + linkedVCPropsDecoder, + parseIntOr, + modulePropsDecoder, + replaceMacros +} from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +export type SimpleValueProps = { + type: ItemType.SIMPLE_VALUE; + valueType: "string" | "image"; + value: string; +} & ( + | { + processValue: "none"; + } + | { + processValue: "avg" | "max" | "min"; + period: number; + }) & + ItemProps & + WithModuleProps & + LinkedVisualConsoleProps; + +/** + * Extract a valid enum value from a raw value type. + * @param valueType Raw value. + */ +const parseValueType = ( + valueType: any // eslint-disable-line @typescript-eslint/no-explicit-any +): SimpleValueProps["valueType"] => { + switch (valueType) { + case "string": + case "image": + return valueType; + default: + return "string"; + } +}; + +/** + * Extract a valid enum value from a raw process value. + * @param processValue Raw value. + */ +const parseProcessValue = ( + processValue: any // eslint-disable-line @typescript-eslint/no-explicit-any +): SimpleValueProps["processValue"] => { + switch (processValue) { + case "none": + case "avg": + case "max": + case "min": + return processValue; + default: + return "none"; + } +}; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the simple value props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function simpleValuePropsDecoder( + data: UnknownObject +): SimpleValueProps | never { + if (typeof data.value !== "string" || data.value.length === 0) { + throw new TypeError("invalid value"); + } + + const processValue = parseProcessValue(data.processValue); + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.SIMPLE_VALUE, + valueType: parseValueType(data.valueType), + value: data.value, + ...(processValue === "none" + ? { processValue } + : { processValue, period: parseIntOr(data.period, 0) }), // Object spread. It will merge the properties of the two objects. + ...modulePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + ...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +export default class SimpleValue extends Item { + protected createDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "simple-value"; + + if (this.props.valueType === "image") { + const img = document.createElement("img"); + img.src = this.props.value; + element.append(img); + } else { + // Add the value to the label and show it. + let text = this.props.value; + let label = this.getLabelWithMacrosReplaced(); + if (label.length > 0) { + text = replaceMacros([{ macro: /\(?_VALUE_\)?/i, value: text }], label); + } + + element.innerHTML = text; + } + + return element; + } + + /** + * @override Item.createLabelDomElement + * Create a new label for the visual console item. + * @return Item label. + */ + protected createLabelDomElement(): HTMLElement { + const element = document.createElement("div"); + element.className = "visual-console-item-label"; + // Always return an empty label. + return element; + } +} diff --git a/visual_console_client/src/items/StaticGraph.ts b/visual_console_client/src/items/StaticGraph.ts new file mode 100644 index 0000000000..0e713dc5f3 --- /dev/null +++ b/visual_console_client/src/items/StaticGraph.ts @@ -0,0 +1,89 @@ +import { + WithModuleProps, + LinkedVisualConsoleProps, + UnknownObject +} from "../types"; + +import { + modulePropsDecoder, + linkedVCPropsDecoder, + notEmptyStringOr +} from "../lib"; +import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; + +export type StaticGraphProps = { + type: ItemType.STATIC_GRAPH; + imageSrc: string; // URL? + showLastValueTooltip: "default" | "enabled" | "disabled"; + statusImageSrc: string | null; // URL? + lastValue: string | null; +} & ItemProps & + (WithModuleProps | LinkedVisualConsoleProps); + +/** + * Extract a valid enum value from a raw unknown value. + * @param showLastValueTooltip Raw value. + */ +const parseShowLastValueTooltip = ( + showLastValueTooltip: any // eslint-disable-line @typescript-eslint/no-explicit-any +): StaticGraphProps["showLastValueTooltip"] => { + switch (showLastValueTooltip) { + case "default": + case "enabled": + case "disabled": + return showLastValueTooltip; + default: + return "default"; + } +}; + +/** + * Build a valid typed object from a raw object. + * This will allow us to ensure the type safety. + * + * @param data Raw object. + * @return An object representing the static graph props. + * @throws Will throw a TypeError if some property + * is missing from the raw object or have an invalid type. + */ +export function staticGraphPropsDecoder( + data: UnknownObject +): StaticGraphProps | never { + if (typeof data.imageSrc !== "string" || data.imageSrc.length === 0) { + throw new TypeError("invalid image src."); + } + + return { + ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + type: ItemType.STATIC_GRAPH, + imageSrc: data.imageSrc, + showLastValueTooltip: parseShowLastValueTooltip(data.showLastValueTooltip), + statusImageSrc: notEmptyStringOr(data.statusImageSrc, null), + lastValue: notEmptyStringOr(data.lastValue, null), + ...modulePropsDecoder(data), // Object spread. It will merge the properties of the two objects. + ...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects. + }; +} + +export default class StaticGraph extends Item { + protected createDomElement(): HTMLElement { + const imgSrc = this.props.statusImageSrc || this.props.imageSrc; + const element = document.createElement("div"); + element.className = "static-graph"; + element.style.background = `url(${imgSrc}) no-repeat`; + element.style.backgroundSize = "contain"; + element.style.backgroundPosition = "center"; + + // Show last value in a tooltip. + if ( + this.props.lastValue !== null && + this.props.showLastValueTooltip !== "disabled" + ) { + element.className = "static-graph image forced_title"; + element.setAttribute("data-use_title_for_force_title", "1"); + element.setAttribute("data-title", this.props.lastValue); + } + + return element; + } +} diff --git a/visual_console_client/src/lib.spec.ts b/visual_console_client/src/lib.spec.ts new file mode 100644 index 0000000000..3330773be7 --- /dev/null +++ b/visual_console_client/src/lib.spec.ts @@ -0,0 +1,120 @@ +import { + parseIntOr, + stringIsEmpty, + notEmptyStringOr, + leftPad, + prefixedCssRules, + decodeBase64, + humanDate, + humanTime, + replaceMacros +} from "./lib"; + +describe("function parseIntOr", () => { + it("should retrieve valid int or a default value", () => { + expect(parseIntOr("Foo", null)).toBe(null); + expect(parseIntOr("1a", null)).toBe(1); + expect(parseIntOr("a1", null)).toBe(null); + expect(parseIntOr("1", null)).toBe(1); + expect(parseIntOr(false, null)).toBe(null); + expect(parseIntOr(true, null)).toBe(null); + expect(parseIntOr(1, null)).toBe(1); + }); +}); + +describe("function stringIsEmpty", () => { + it("should check properly if a string is empry or not", () => { + expect(stringIsEmpty()).toBe(true); + expect(stringIsEmpty("")).toBe(true); + expect(stringIsEmpty("foo")).toBe(false); + expect(stringIsEmpty("bar")).toBe(false); + }); +}); + +describe("function notEmptyStringOr", () => { + it("should retrieve not empty string or a default value", () => { + expect(notEmptyStringOr("", null)).toBe(null); + expect(notEmptyStringOr("Foo", null)).toBe("Foo"); + expect(notEmptyStringOr(1, 1)).toBe(1); + expect(notEmptyStringOr(1, 0)).toBe(0); + expect(notEmptyStringOr("", 0)).toBe(0); + expect(notEmptyStringOr("Foo", "Bar")).toBe("Foo"); + expect(notEmptyStringOr(0, "Bar")).toBe("Bar"); + }); +}); + +describe("function leftPad", () => { + it("should pad properly", () => { + expect(leftPad(1, 2, 0)).toBe("01"); + expect(leftPad(1, 4, 0)).toBe("0001"); + expect(leftPad(1, 4, "0")).toBe("0001"); + expect(leftPad("1", 4, "0")).toBe("0001"); + expect(leftPad(10, 4, 0)).toBe("0010"); + expect(leftPad("bar", 6, "foo")).toBe("foobar"); + expect(leftPad("bar", 11, "foo")).toBe("foofoofobar"); + expect(leftPad("bar", 4, "foo")).toBe("fbar"); + expect(leftPad("bar", 2, "foo")).toBe("ar"); + expect(leftPad("bar", 3, "foo")).toBe("bar"); + }); +}); + +describe("function prefixedCssRules", () => { + it("should add the prefixes to the rules", () => { + const rules = prefixedCssRules("transform", "rotate(0)"); + expect(rules).toContainEqual("transform: rotate(0);"); + expect(rules).toContainEqual("-webkit-transform: rotate(0);"); + expect(rules).toContainEqual("-moz-transform: rotate(0);"); + expect(rules).toContainEqual("-ms-transform: rotate(0);"); + expect(rules).toContainEqual("-o-transform: rotate(0);"); + expect(rules).toHaveLength(5); + }); +}); + +describe("function decodeBase64", () => { + it("should decode the base64 without errors", () => { + expect(decodeBase64("SGkgSSdtIGRlY29kZWQ=")).toEqual("Hi I'm decoded"); + expect(decodeBase64("Rk9PQkFSQkFa")).toEqual("FOOBARBAZ"); + expect(decodeBase64("eyJpZCI6MSwibmFtZSI6ImZvbyJ9")).toEqual( + '{"id":1,"name":"foo"}' + ); + expect( + decodeBase64("PGRpdj5Cb3ggPHA+UGFyYWdyYXBoPC9wPjxociAvPjwvZGl2Pg==") + ).toEqual("
      Box

      Paragraph


      "); + }); +}); + +describe("humanDate function", () => { + it("should return the date with padded 0's", () => { + const expected = "01/02/0123"; + const date = new Date(`02/01/0123 12:00:00`); + const digitalDate = humanDate(date); + expect(digitalDate).toBe(expected); + }); +}); + +describe("humanTime function", () => { + it("should return the time with padded 0's when hours/minutes/seconds are less than 10", () => { + const expected = "01:02:03"; + const date = new Date(`01/01/1970 ${expected}`); + const digitalTime = humanTime(date); + expect(digitalTime).toBe(expected); + }); +}); + +describe("replaceMacros function", () => { + const macros = [ + { macro: "_foo_", value: "foo" }, + { macro: "_bar_", value: "bar" }, + { macro: "_baz_", value: "baz" } + ]; + + it("should not replace anything if it doesn't find any macro", () => { + const text = "Lorem Ipsum"; + expect(replaceMacros(macros, text)).toBe(text); + }); + + it("should replace the macros", () => { + const text = "Lorem _foo_ Ipsum _baz_"; + expect(replaceMacros(macros, text)).toBe("Lorem foo Ipsum baz"); + }); +}); diff --git a/visual_console_client/src/lib.ts b/visual_console_client/src/lib.ts new file mode 100644 index 0000000000..57b4f1c221 --- /dev/null +++ b/visual_console_client/src/lib.ts @@ -0,0 +1,335 @@ +import { + UnknownObject, + Position, + Size, + WithAgentProps, + WithModuleProps, + LinkedVisualConsoleProps, + LinkedVisualConsolePropsStatus +} from "./types"; + +/** + * Return a number or a default value from a raw value. + * @param value Raw value from which we will try to extract a valid number. + * @param defaultValue Default value to use if we cannot extract a valid number. + * @return A valid number or the default value. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function parseIntOr(value: any, defaultValue: T): number | T { + if (typeof value === "number") return value; + if (typeof value === "string" && value.length > 0 && !isNaN(parseInt(value))) + return parseInt(value); + else return defaultValue; +} + +/** + * Return a number or a default value from a raw value. + * @param value Raw value from which we will try to extract a valid number. + * @param defaultValue Default value to use if we cannot extract a valid number. + * @return A valid number or the default value. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function parseFloatOr(value: any, defaultValue: T): number | T { + if (typeof value === "number") return value; + if ( + typeof value === "string" && + value.length > 0 && + !isNaN(parseFloat(value)) + ) + return parseFloat(value); + else return defaultValue; +} + +/** + * Check if a string exists and it's not empty. + * @param value Value to check. + * @return The check result. + */ +export function stringIsEmpty(value?: string | null): boolean { + return value == null || value.length === 0; +} + +/** + * Return a not empty string or a default value from a raw value. + * @param value Raw value from which we will try to extract a non empty string. + * @param defaultValue Default value to use if we cannot extract a non empty string. + * @return A non empty string or the default value. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function notEmptyStringOr(value: any, defaultValue: T): string | T { + return typeof value === "string" && value.length > 0 ? value : defaultValue; +} + +/** + * Return a boolean from a raw value. + * @param value Raw value from which we will try to extract the boolean. + * @return A valid boolean value. false by default. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function parseBoolean(value: any): boolean { + if (typeof value === "boolean") return value; + else if (typeof value === "number") return value > 0; + else if (typeof value === "string") return value === "1" || value === "true"; + else return false; +} + +/** + * Pad the current string with another string (multiple times, if needed) + * until the resulting string reaches the given length. + * The padding is applied from the start (left) of the current string. + * @param value Text that needs to be padded. + * @param length Length of the returned text. + * @param pad Text to add. + * @return Padded text. + */ +export function leftPad( + value: string | number, + length: number, + pad: string | number = " " +): string { + if (typeof value === "number") value = `${value}`; + if (typeof pad === "number") pad = `${pad}`; + + const diffLength = length - value.length; + if (diffLength === 0) return value; + if (diffLength < 0) return value.substr(Math.abs(diffLength)); + + if (diffLength === pad.length) return `${pad}${value}`; + if (diffLength < pad.length) return `${pad.substring(0, diffLength)}${value}`; + + const repeatTimes = Math.floor(diffLength / pad.length); + const restLength = diffLength - pad.length * repeatTimes; + + let newPad = ""; + for (let i = 0; i < repeatTimes; i++) newPad += pad; + + if (restLength === 0) return `${newPad}${value}`; + return `${newPad}${pad.substring(0, restLength)}${value}`; +} + +/* Decoders */ + +/** + * Build a valid typed object from a raw object. + * @param data Raw object. + * @return An object representing the position. + */ +export function positionPropsDecoder(data: UnknownObject): Position { + return { + x: parseIntOr(data.x, 0), + y: parseIntOr(data.y, 0) + }; +} + +/** + * Build a valid typed object from a raw object. + * @param data Raw object. + * @return An object representing the size. + * @throws Will throw a TypeError if the width and height are not valid numbers. + */ +export function sizePropsDecoder(data: UnknownObject): Size | never { + if ( + data.width == null || + isNaN(parseInt(data.width)) || + data.height == null || + isNaN(parseInt(data.height)) + ) { + throw new TypeError("invalid size."); + } + + return { + width: parseInt(data.width), + height: parseInt(data.height) + }; +} + +/** + * Build a valid typed object from a raw object. + * @param data Raw object. + * @return An object representing the agent properties. + */ +export function agentPropsDecoder(data: UnknownObject): WithAgentProps { + const agentProps: WithAgentProps = { + agentId: parseIntOr(data.agent, null), + agentName: notEmptyStringOr(data.agentName, null), + agentAlias: notEmptyStringOr(data.agentAlias, null), + agentDescription: notEmptyStringOr(data.agentDescription, null), + agentAddress: notEmptyStringOr(data.agentAddress, null) + }; + + return data.metaconsoleId != null + ? { + metaconsoleId: data.metaconsoleId, + ...agentProps // Object spread: http://es6-features.org/#SpreadOperator + } + : agentProps; +} + +/** + * Build a valid typed object from a raw object. + * @param data Raw object. + * @return An object representing the module and agent properties. + */ +export function modulePropsDecoder(data: UnknownObject): WithModuleProps { + return { + moduleId: parseIntOr(data.moduleId, null), + moduleName: notEmptyStringOr(data.moduleName, null), + moduleDescription: notEmptyStringOr(data.moduleDescription, null), + ...agentPropsDecoder(data) // Object spread: http://es6-features.org/#SpreadOperator + }; +} + +/** + * Build a valid typed object from a raw object. + * @param data Raw object. + * @return An object representing the linked visual console properties. + * @throws Will throw a TypeError if the status calculation properties are invalid. + */ +export function linkedVCPropsDecoder( + data: UnknownObject +): LinkedVisualConsoleProps | never { + // Object destructuring: http://es6-features.org/#ObjectMatchingShorthandNotation + const { + metaconsoleId, + linkedLayoutId: id, + linkedLayoutAgentId: agentId + } = data; + + let linkedLayoutStatusProps: LinkedVisualConsolePropsStatus = { + linkedLayoutStatusType: "default" + }; + switch (data.linkedLayoutStatusType) { + case "weight": { + const weight = parseIntOr(data.linkedLayoutStatusTypeWeight, null); + if (weight == null) + throw new TypeError("invalid status calculation properties."); + + if (data.linkedLayoutStatusTypeWeight) + linkedLayoutStatusProps = { + linkedLayoutStatusType: "weight", + linkedLayoutStatusTypeWeight: weight + }; + break; + } + case "service": { + const warningThreshold = parseIntOr( + data.linkedLayoutStatusTypeWarningThreshold, + null + ); + const criticalThreshold = parseIntOr( + data.linkedLayoutStatusTypeCriticalThreshold, + null + ); + if (warningThreshold == null || criticalThreshold == null) { + throw new TypeError("invalid status calculation properties."); + } + + linkedLayoutStatusProps = { + linkedLayoutStatusType: "service", + linkedLayoutStatusTypeWarningThreshold: warningThreshold, + linkedLayoutStatusTypeCriticalThreshold: criticalThreshold + }; + break; + } + } + + const linkedLayoutBaseProps = { + linkedLayoutId: parseIntOr(id, null), + linkedLayoutAgentId: parseIntOr(agentId, null), + ...linkedLayoutStatusProps // Object spread: http://es6-features.org/#SpreadOperator + }; + + return metaconsoleId != null + ? { + metaconsoleId, + ...linkedLayoutBaseProps // Object spread: http://es6-features.org/#SpreadOperator + } + : linkedLayoutBaseProps; +} + +/** + * To get a CSS rule with the most used prefixes. + * @param ruleName Name of the CSS rule. + * @param ruleValue Value of the CSS rule. + * @return An array of rules with the prefixes applied. + */ +export function prefixedCssRules( + ruleName: string, + ruleValue: string +): string[] { + const rule = `${ruleName}: ${ruleValue};`; + return [ + `-webkit-${rule}`, + `-moz-${rule}`, + `-ms-${rule}`, + `-o-${rule}`, + `${rule}` + ]; +} + +/** + * Decode a base64 string. + * @param input Data encoded using base64. + * @return Decoded data. + */ +export function decodeBase64(input: string): string { + return decodeURIComponent(escape(window.atob(input))); +} + +/** + * Generate a date representation with the format 'd/m/Y'. + * @param initialDate Date to be used instead of a generated one. + * @param locale Locale to use if localization is required and available. + * @example 24/02/2020. + * @return Date representation. + */ +export function humanDate(date: Date, locale: string | null = null): string { + if (locale && Intl && Intl.DateTimeFormat) { + // Format using the user locale. + const options: Intl.DateTimeFormatOptions = { + day: "2-digit", + month: "2-digit", + year: "numeric" + }; + return Intl.DateTimeFormat(locale, options).format(date); + } else { + // Use getDate, getDay returns the week day. + const day = leftPad(date.getDate(), 2, 0); + // The getMonth function returns the month starting by 0. + const month = leftPad(date.getMonth() + 1, 2, 0); + const year = leftPad(date.getFullYear(), 4, 0); + + // Format: 'd/m/Y'. + return `${day}/${month}/${year}`; + } +} + +/** + * Generate a time representation with the format 'hh:mm:ss'. + * @param initialDate Date to be used instead of a generated one. + * @example 01:34:09. + * @return Time representation. + */ +export function humanTime(date: Date): string { + const hours = leftPad(date.getHours(), 2, 0); + const minutes = leftPad(date.getMinutes(), 2, 0); + const seconds = leftPad(date.getSeconds(), 2, 0); + + return `${hours}:${minutes}:${seconds}`; +} + +interface Macro { + macro: string | RegExp; + value: string; +} +/** + * Replace the macros of a text. + * @param macros List of macros and their replacements. + * @param text Text in which we need to replace the macros. + */ +export function replaceMacros(macros: Macro[], text: string): string { + return macros.reduce( + (acc, { macro, value }) => acc.replace(macro, value), + text + ); +} diff --git a/visual_console_client/src/main.css b/visual_console_client/src/main.css new file mode 100644 index 0000000000..427c8895af --- /dev/null +++ b/visual_console_client/src/main.css @@ -0,0 +1,16 @@ +#visual-console-container { + margin: 0px auto; + position: relative; + background-repeat: no-repeat; + background-size: 100% 100%; + background-position: center; +} + +.visual-console-item { + position: absolute; + display: flex; + flex-direction: initial; + justify-items: center; + align-items: center; + user-select: text; +} diff --git a/visual_console_client/src/types.ts b/visual_console_client/src/types.ts new file mode 100644 index 0000000000..79dee56e74 --- /dev/null +++ b/visual_console_client/src/types.ts @@ -0,0 +1,47 @@ +export interface UnknownObject { + [key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any +} + +export interface Position { + x: number; + y: number; +} + +export interface Size { + width: number; + height: number; +} + +export interface WithAgentProps { + metaconsoleId?: number | null; + agentId: number | null; + agentName: string | null; + agentAlias: string | null; + agentDescription: string | null; + agentAddress: string | null; +} + +export interface WithModuleProps extends WithAgentProps { + moduleId: number | null; + moduleName: string | null; + moduleDescription: string | null; +} + +export type LinkedVisualConsolePropsStatus = + | { + linkedLayoutStatusType: "default"; + } + | { + linkedLayoutStatusType: "weight"; + linkedLayoutStatusTypeWeight: number; + } + | { + linkedLayoutStatusType: "service"; + linkedLayoutStatusTypeWarningThreshold: number; + linkedLayoutStatusTypeCriticalThreshold: number; + }; +export type LinkedVisualConsoleProps = { + metaconsoleId?: number | null; + linkedLayoutId: number | null; + linkedLayoutAgentId: number | null; +} & LinkedVisualConsolePropsStatus; diff --git a/visual_console_client/tsconfig.json b/visual_console_client/tsconfig.json new file mode 100644 index 0000000000..5f047a33d6 --- /dev/null +++ b/visual_console_client/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "es6", + "strict": true, + "alwaysStrict": true, + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "sourceMap": true, + // "isolatedModules": true, + "noEmit": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "pretty": true + }, + "include": ["**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/visual_console_client/webpack.config.js b/visual_console_client/webpack.config.js new file mode 100644 index 0000000000..ffce749d99 --- /dev/null +++ b/visual_console_client/webpack.config.js @@ -0,0 +1,104 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const path = require("path"); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const CleanWebpackPlugin = require("clean-webpack-plugin"); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); + +const dev = process.env.NODE_ENV !== "production"; +const entry = path.join(__dirname, "src", "index.ts"); +const buildPath = path.join( + __dirname, + "..", + process.env.BUILD_PATH && process.env.BUILD_PATH.length > 0 + ? process.env.BUILD_PATH + : "build" +); + +module.exports = { + mode: dev ? "development" : "production", + entry, // Start from this file. + output: { + path: buildPath, // The files will be created here. + // filename: dev ? "vc.[name].min.js" : "vc.[name].[chunkhash:8].min.js" + filename: "vc.[name].min.js" + }, + devtool: "source-map", + resolve: { + extensions: [".ts", ".js", ".json"] + }, + module: { + rules: [ + // Loader for the Typescript compiler. + { + test: /\.ts$/, + loader: "awesome-typescript-loader" + }, + // This loader builds a main CSS file from all the CSS imports across the files. + { + test: /\.css$/, + loader: [ + // https://github.com/webpack-contrib/mini-css-extract-plugin + { + loader: MiniCssExtractPlugin.loader, + options: { + hot: true, // if you want HMR - we try to automatically inject hot reloading but if it's not working, add it to the config + reloadAll: true // when desperation kicks in - this is a brute force HMR flag + } + }, + // https://webpack.js.org/loaders/css-loader + { + loader: "css-loader", + options: { + sourceMap: true + } + }, + // To post process CSS and add some things like prefixes to the rules. e.g.: -webkit-... + // https://github.com/postcss/postcss-loader + { + loader: "postcss-loader", + options: { + plugins: () => [ + // To improve the support for old browsers. + require("autoprefixer")({ + browsers: ["> 1%", "last 2 versions"] + }) + ] + } + } + ] + }, + // To allow the use of file imports. The imported files are transformed into + // data uris if they are small enough or it returns a path to the file. + // https://webpack.js.org/loaders/url-loader + { + test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/, + loader: "url-loader", + options: { + limit: 10000, + // name: "[name].[hash:8].[ext]" + name: "[name].[ext]" + } + } + ] + }, + plugins: [ + // This plugin will remove all files inside Webpack's output.path directory, + // as well as all unused webpack assets after every successful rebuild. + new CleanWebpackPlugin(), + // Options for the plugin which extract the CSS files to build a main file. + new MiniCssExtractPlugin({ + // Options similar to the same options in webpackOptions.output + // both options are optional + // filename: dev ? "vc.[name].css" : "vc.[name].[contenthash:8].css", + filename: "vc.[name].css", + // Disable to remove warnings about conflicting order between imports. + orderWarning: true + }) + ], + // Static server which runs the playground on npm start. + devServer: { + open: true, + contentBase: "playground" + } +};