diff --git a/src/Umbraco.Core/Collections/ConcurrentHashSet.cs b/src/Umbraco.Core/Collections/ConcurrentHashSet.cs index 4cad6e9f15..54367ed588 100644 --- a/src/Umbraco.Core/Collections/ConcurrentHashSet.cs +++ b/src/Umbraco.Core/Collections/ConcurrentHashSet.cs @@ -70,10 +70,7 @@ namespace Umbraco.Core.Collections /// The number of elements contained in the . /// /// 2 - public int Count - { - get { return GetThreadSafeClone().Count; } - } + public int Count => GetThreadSafeClone().Count; /// /// Gets a value indicating whether the is read-only. @@ -81,10 +78,7 @@ namespace Umbraco.Core.Collections /// /// true if the is read-only; otherwise, false. /// - public bool IsReadOnly - { - get { return false; } - } + public bool IsReadOnly => false; /// /// Adds an item to the . diff --git a/src/Umbraco.Core/Constants-Indexes.cs b/src/Umbraco.Core/Constants-Indexes.cs new file mode 100644 index 0000000000..c73a170b62 --- /dev/null +++ b/src/Umbraco.Core/Constants-Indexes.cs @@ -0,0 +1,19 @@ +using System; +using System.ComponentModel; + +namespace Umbraco.Core +{ + public static partial class Constants + { + public static class UmbracoIndexes + { + public const string InternalIndexName = InternalIndexPath + "Index"; + public const string ExternalIndexName = ExternalIndexPath + "Index"; + public const string MembersIndexName = MembersIndexPath + "Index"; + + public const string InternalIndexPath = "Internal"; + public const string ExternalIndexPath = "External"; + public const string MembersIndexPath = "Members"; + } + } +} diff --git a/src/Umbraco.Core/EnumerableExtensions.cs b/src/Umbraco.Core/EnumerableExtensions.cs index c455fadad7..4fa013c095 100644 --- a/src/Umbraco.Core/EnumerableExtensions.cs +++ b/src/Umbraco.Core/EnumerableExtensions.cs @@ -1,11 +1,6 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Text; -using Umbraco.Core.Logging; namespace Umbraco.Core { @@ -14,6 +9,18 @@ namespace Umbraco.Core /// public static class EnumerableExtensions { + /// + /// Wraps this object instance into an IEnumerable{T} consisting of a single item. + /// + /// Type of the object. + /// The instance that will be wrapped. + /// An IEnumerable{T} consisting of a single item. + public static IEnumerable Yield(this T item) + { + // see EnumeratorBenchmarks - this is faster, and allocates less, than returning an array + yield return item; + } + public static IEnumerable> InGroupsOf(this IEnumerable source, int groupSize) { if (source == null) diff --git a/src/Umbraco.Core/Models/GridValue.cs b/src/Umbraco.Core/Models/GridValue.cs index 717fcd2f88..237385f3f4 100644 --- a/src/Umbraco.Core/Models/GridValue.cs +++ b/src/Umbraco.Core/Models/GridValue.cs @@ -5,6 +5,8 @@ using Newtonsoft.Json.Linq; namespace Umbraco.Core.Models { + //TODO: Make a property value converter for this! + /// /// A model representing the value saved for the grid /// @@ -19,7 +21,7 @@ namespace Umbraco.Core.Models public class GridSection { [JsonProperty("grid")] - public string Grid { get; set; } + public string Grid { get; set; } //fixme: what is this? [JsonProperty("rows")] public IEnumerable Rows { get; set; } @@ -46,7 +48,7 @@ namespace Umbraco.Core.Models public class GridArea { [JsonProperty("grid")] - public string Grid { get; set; } + public string Grid { get; set; } //fixme: what is this? [JsonProperty("controls")] public IEnumerable Controls { get; set; } diff --git a/src/Umbraco.Core/Models/PagedResult.cs b/src/Umbraco.Core/Models/PagedResult.cs index 653712d9f8..ef4d4efdfd 100644 --- a/src/Umbraco.Core/Models/PagedResult.cs +++ b/src/Umbraco.Core/Models/PagedResult.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Models if (pageSize > 0) { - TotalPages = (long)Math.Ceiling(totalItems / (Decimal)pageSize); + TotalPages = (long)Math.Ceiling(totalItems / (decimal)pageSize); } else { diff --git a/src/Umbraco.Core/Models/PublicAccessEntry.cs b/src/Umbraco.Core/Models/PublicAccessEntry.cs index e93dc56e35..df2d9f9ddc 100644 --- a/src/Umbraco.Core/Models/PublicAccessEntry.cs +++ b/src/Umbraco.Core/Models/PublicAccessEntry.cs @@ -21,6 +21,10 @@ namespace Umbraco.Core.Models public PublicAccessEntry(IContent protectedNode, IContent loginNode, IContent noAccessNode, IEnumerable ruleCollection) { + if (protectedNode == null) throw new ArgumentNullException(nameof(protectedNode)); + if (loginNode == null) throw new ArgumentNullException(nameof(loginNode)); + if (noAccessNode == null) throw new ArgumentNullException(nameof(noAccessNode)); + LoginNodeId = loginNode.Id; NoAccessNodeId = noAccessNode.Id; _protectedNodeId = protectedNode.Id; diff --git a/src/Umbraco.Core/ObjectExtensions.cs b/src/Umbraco.Core/ObjectExtensions.cs index 6c2fd85dbe..1bc2fb48a5 100644 --- a/src/Umbraco.Core/ObjectExtensions.cs +++ b/src/Umbraco.Core/ObjectExtensions.cs @@ -723,8 +723,8 @@ namespace Umbraco.Core { return typeConverter; } - - TypeConverter converter = TypeDescriptor.GetConverter(target); + + var converter = TypeDescriptor.GetConverter(target); if (converter.CanConvertFrom(source)) { return DestinationTypeConverterCache[key] = converter; diff --git a/src/Umbraco.Core/PropertyEditors/DataEditor.cs b/src/Umbraco.Core/PropertyEditors/DataEditor.cs index 2d0b34a849..f3fc4f669b 100644 --- a/src/Umbraco.Core/PropertyEditors/DataEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DataEditor.cs @@ -153,6 +153,9 @@ namespace Umbraco.Core.PropertyEditors set => _defaultConfiguration = value; } + /// + public virtual IPropertyIndexValueFactory PropertyIndexValueFactory => new DefaultPropertyIndexValueFactory(); + /// /// Creates a value editor instance. /// diff --git a/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs new file mode 100644 index 0000000000..413f31d79e --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Umbraco.Core.Models; + +namespace Umbraco.Core.PropertyEditors +{ + /// + /// Provides a default implementation for , returning a single field to index containing the property value. + /// + public class DefaultPropertyIndexValueFactory : IPropertyIndexValueFactory + { + /// + public IEnumerable>> GetIndexValues(Property property, string culture, string segment, bool published) + { + yield return new KeyValuePair>( + property.Alias, + property.GetValue(culture, segment, published).Yield()); + } + } +} diff --git a/src/Umbraco.Core/PropertyEditors/IDataEditor.cs b/src/Umbraco.Core/PropertyEditors/IDataEditor.cs index 8137101826..f109620ad9 100644 --- a/src/Umbraco.Core/PropertyEditors/IDataEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/IDataEditor.cs @@ -65,5 +65,10 @@ namespace Umbraco.Core.PropertyEditors /// Is expected to throw if the editor does not support being configured, e.g. for most parameter editors. /// IConfigurationEditor GetConfigurationEditor(); + + /// + /// Gets the index value factory for the editor. + /// + IPropertyIndexValueFactory PropertyIndexValueFactory { get; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/PropertyEditors/IPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/IPropertyIndexValueFactory.cs new file mode 100644 index 0000000000..fd4e272f08 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/IPropertyIndexValueFactory.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using Umbraco.Core.Models; + +namespace Umbraco.Core.PropertyEditors +{ + /// + /// Represents a property index value factory. + /// + public interface IPropertyIndexValueFactory + { + /// + /// Gets the index values for a property. + /// + /// + /// Returns key-value pairs, where keys are indexed field names. By default, that would be the property alias, + /// and there would be only one pair, but some implementations (see for instance the grid one) may return more than + /// one pair, with different indexed field names. + /// And then, values are an enumerable of objects, because each indexed field can in turn have multiple + /// values. By default, there would be only one object: the property value. But some implementations may return + /// more than one value for a given field. + /// + IEnumerable>> GetIndexValues(Property property, string culture, string segment, bool published); + } +} diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index 22138a5e8c..7915bbe24b 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -176,10 +176,8 @@ namespace Umbraco.Core.Services /// The page number. /// The page size. /// Total number of documents. - /// A field to order by. - /// The ordering direction. - /// A flag indicating whether the ordering field is a system field. /// Query filter. + /// Ordering infos. IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords, IQuery filter = null, Ordering ordering = null); diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index 461b1d3c1e..03a371204c 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -540,7 +540,7 @@ namespace Umbraco.Core public static string StripHtml(this string text) { const string pattern = @"<(.|\n)*?>"; - return Regex.Replace(text, pattern, string.Empty); + return Regex.Replace(text, pattern, string.Empty, RegexOptions.Compiled); } /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 7da0189345..13a81aa74b 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -313,6 +313,7 @@ + @@ -442,6 +443,7 @@ + @@ -450,6 +452,7 @@ + diff --git a/src/Umbraco.Examine/BaseValueSetBuilder.cs b/src/Umbraco.Examine/BaseValueSetBuilder.cs new file mode 100644 index 0000000000..22d379d148 --- /dev/null +++ b/src/Umbraco.Examine/BaseValueSetBuilder.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using System.Linq; +using Examine; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Examine +{ + + /// + public abstract class BaseValueSetBuilder : IValueSetBuilder + where TContent : IContentBase + { + protected bool PublishedValuesOnly { get; } + private readonly PropertyEditorCollection _propertyEditors; + + protected BaseValueSetBuilder(PropertyEditorCollection propertyEditors, bool publishedValuesOnly) + { + PublishedValuesOnly = publishedValuesOnly; + _propertyEditors = propertyEditors ?? throw new System.ArgumentNullException(nameof(propertyEditors)); + } + + /// + public abstract IEnumerable GetValueSets(params TContent[] content); + + protected void AddPropertyValue(Property property, string culture, string segment, IDictionary> values) + { + var editor = _propertyEditors[property.PropertyType.PropertyEditorAlias]; + if (editor == null) return; + + var indexVals = editor.PropertyIndexValueFactory.GetIndexValues(property, culture, segment, PublishedValuesOnly); + foreach (var keyVal in indexVals) + { + if (keyVal.Key.IsNullOrWhiteSpace()) continue; + + var cultureSuffix = culture == null ? string.Empty : "_" + culture; + + foreach (var val in keyVal.Value) + { + switch (val) + { + //only add the value if its not null or empty (we'll check for string explicitly here too) + case null: + continue; + case string strVal: + { + if (strVal.IsNullOrWhiteSpace()) return; + var key = $"{keyVal.Key}{cultureSuffix}"; + if (values.TryGetValue(key, out var v)) + values[key] = new List(v) { val }.ToArray(); + else + values.Add($"{keyVal.Key}{cultureSuffix}", val.Yield()); + } + break; + default: + { + var key = $"{keyVal.Key}{cultureSuffix}"; + if (values.TryGetValue(key, out var v)) + values[key] = new List(v) { val }.ToArray(); + else + values.Add($"{keyVal.Key}{cultureSuffix}", val.Yield()); + } + + break; + } + } + } + } + } + +} diff --git a/src/Umbraco.Examine/Config/IndexFieldCollection.cs b/src/Umbraco.Examine/Config/IndexFieldCollection.cs new file mode 100644 index 0000000000..063c157dbe --- /dev/null +++ b/src/Umbraco.Examine/Config/IndexFieldCollection.cs @@ -0,0 +1,47 @@ +using System.Configuration; + +namespace Umbraco.Examine.Config +{ + public sealed class IndexFieldCollection : ConfigurationElementCollection + { + #region Overridden methods to define collection + protected override ConfigurationElement CreateNewElement() + { + return new ConfigIndexField(); + } + protected override object GetElementKey(ConfigurationElement element) + { + ConfigIndexField field = (ConfigIndexField)element; + return field.Name; + } + + public override bool IsReadOnly() + { + return false; + } + #endregion + + /// + /// Adds an index field to the collection + /// + /// + public void Add(ConfigIndexField field) + { + BaseAdd(field, true); + } + + /// + /// Default property for accessing an IndexField definition + /// + /// Field Name + /// + public new ConfigIndexField this[string name] + { + get + { + return (ConfigIndexField)this.BaseGet(name); + } + } + + } +} \ No newline at end of file diff --git a/src/Umbraco.Examine/Config/IndexSet.cs b/src/Umbraco.Examine/Config/IndexSet.cs index 33b67412f2..65b1cd5aec 100644 --- a/src/Umbraco.Examine/Config/IndexSet.cs +++ b/src/Umbraco.Examine/Config/IndexSet.cs @@ -11,48 +11,6 @@ namespace Umbraco.Examine.Config [ConfigurationProperty("SetName", IsRequired = true, IsKey = true)] public string SetName => (string)this["SetName"]; - private string _indexPath = ""; - - /// - /// The folder path of where the lucene index is stored - /// - /// The index path. - /// - /// This can be set at runtime but will not be persisted to the configuration file - /// - [ConfigurationProperty("IndexPath", IsRequired = true, IsKey = false)] - public string IndexPath - { - get - { - if (string.IsNullOrEmpty(_indexPath)) - _indexPath = (string)this["IndexPath"]; - - return _indexPath; - } - set => _indexPath = value; - } - - /// - /// Returns the DirectoryInfo object for the index path. - /// - /// The index directory. - public DirectoryInfo IndexDirectory - { - get - { - //TODO: Get this out of the index set. We need to use the Indexer's DataService to lookup the folder so it can be unit tested. Probably need DataServices on the searcher then too - - //we need to de-couple the context - if (HttpContext.Current != null) - return new DirectoryInfo(HttpContext.Current.Server.MapPath(this.IndexPath)); - else if (HostingEnvironment.ApplicationID != null) - return new DirectoryInfo(HostingEnvironment.MapPath(this.IndexPath)); - else - return new DirectoryInfo(this.IndexPath); - } - } - /// /// When this property is set, the indexing will only index documents that are descendants of this node. /// diff --git a/src/Umbraco.Examine/Config/IndexSetCollection.cs b/src/Umbraco.Examine/Config/IndexSetCollection.cs index 5ba2382563..bfce8e4cce 100644 --- a/src/Umbraco.Examine/Config/IndexSetCollection.cs +++ b/src/Umbraco.Examine/Config/IndexSetCollection.cs @@ -3,50 +3,6 @@ namespace Umbraco.Examine.Config { - public sealed class IndexFieldCollection : ConfigurationElementCollection - { - #region Overridden methods to define collection - protected override ConfigurationElement CreateNewElement() - { - return new ConfigIndexField(); - } - protected override object GetElementKey(ConfigurationElement element) - { - ConfigIndexField field = (ConfigIndexField)element; - return field.Name; - } - - public override bool IsReadOnly() - { - return false; - } - #endregion - - /// - /// Adds an index field to the collection - /// - /// - public void Add(ConfigIndexField field) - { - BaseAdd(field, true); - } - - /// - /// Default property for accessing an IndexField definition - /// - /// Field Name - /// - public new ConfigIndexField this[string name] - { - get - { - return (ConfigIndexField)this.BaseGet(name); - } - } - - } - - public sealed class IndexSetCollection : ConfigurationElementCollection { #region Overridden methods to define collection diff --git a/src/Umbraco.Examine/ContentIndexPopulator.cs b/src/Umbraco.Examine/ContentIndexPopulator.cs new file mode 100644 index 0000000000..d1255b4d46 --- /dev/null +++ b/src/Umbraco.Examine/ContentIndexPopulator.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Examine; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.Services; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using Umbraco.Core.Persistence.Querying; + +namespace Umbraco.Examine +{ + + /// + /// Performs the data lookups required to rebuild a content index + /// + public class ContentIndexPopulator : IndexPopulator + { + private readonly IContentService _contentService; + private readonly IValueSetBuilder _contentValueSetBuilder; + + /// + /// This is a static query, it's parameters don't change so store statically + /// + private static IQuery _publishedQuery; + + private readonly bool _publishedValuesOnly; + private readonly int? _parentId; + + /// + /// Default constructor to lookup all content data + /// + /// + /// + /// + public ContentIndexPopulator(IContentService contentService, ISqlContext sqlContext, IContentValueSetBuilder contentValueSetBuilder) + : this(false, null, contentService, sqlContext, contentValueSetBuilder) + { + } + + /// + /// Optional constructor allowing specifying custom query parameters + /// + /// + /// + /// + /// + /// + public ContentIndexPopulator(bool publishedValuesOnly, int? parentId, IContentService contentService, ISqlContext sqlContext, IValueSetBuilder contentValueSetBuilder) + { + if (sqlContext == null) throw new ArgumentNullException(nameof(sqlContext)); + _contentService = contentService ?? throw new ArgumentNullException(nameof(contentService)); + _contentValueSetBuilder = contentValueSetBuilder ?? throw new ArgumentNullException(nameof(contentValueSetBuilder)); + if (_publishedQuery != null) + _publishedQuery = sqlContext.Query().Where(x => x.Published); + _publishedValuesOnly = publishedValuesOnly; + _parentId = parentId; + + RegisterIndex(Constants.UmbracoIndexes.InternalIndexName); + RegisterIndex(Constants.UmbracoIndexes.ExternalIndexName); + } + + protected override void PopulateIndexes(IEnumerable indexes) + { + const int pageSize = 10000; + var pageIndex = 0; + + var contentParentId = -1; + if (_parentId.HasValue && _parentId.Value > 0) + { + contentParentId = _parentId.Value; + } + IContent[] content; + + do + { + if (!_publishedValuesOnly) + { + content = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out _).ToArray(); + } + else + { + //add the published filter + //note: We will filter for published variants in the validator + content = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out _, + _publishedQuery, Ordering.By("Path", Direction.Ascending)).ToArray(); + } + + if (content.Length > 0) + { + // ReSharper disable once PossibleMultipleEnumeration + foreach (var index in indexes) + index.IndexItems(_contentValueSetBuilder.GetValueSets(content)); + } + + pageIndex++; + } while (content.Length == pageSize); + } + } +} diff --git a/src/Umbraco.Examine/ContentValueSetBuilder.cs b/src/Umbraco.Examine/ContentValueSetBuilder.cs new file mode 100644 index 0000000000..39ffab98d9 --- /dev/null +++ b/src/Umbraco.Examine/ContentValueSetBuilder.cs @@ -0,0 +1,106 @@ +using Examine; +using System.Collections.Generic; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; +using Umbraco.Core.Strings; + +namespace Umbraco.Examine +{ + /// + /// Builds s for items + /// + public class ContentValueSetBuilder : BaseValueSetBuilder, IContentValueSetBuilder, IPublishedContentValueSetBuilder + { + private readonly IEnumerable _urlSegmentProviders; + private readonly IUserService _userService; + + public ContentValueSetBuilder(PropertyEditorCollection propertyEditors, + IEnumerable urlSegmentProviders, + IUserService userService, + bool publishedValuesOnly) + : base(propertyEditors, publishedValuesOnly) + { + _urlSegmentProviders = urlSegmentProviders; + _userService = userService; + } + + /// + public override IEnumerable GetValueSets(params IContent[] content) + { + //TODO: There is a lot of boxing going on here and ultimately all values will be boxed by Lucene anyways + // but I wonder if there's a way to reduce the boxing that we have to do or if it will matter in the end since + // Lucene will do it no matter what? One idea was to create a `FieldValue` struct which would contain `object`, `object[]`, `ValueType` and `ValueType[]` + // references and then each array is an array of `FieldValue[]` and values are assigned accordingly. Not sure if it will make a difference or not. + + foreach (var c in content) + { + var isVariant = c.ContentType.VariesByCulture(); + + var urlValue = c.GetUrlSegment(_urlSegmentProviders); //Always add invariant urlName + var values = new Dictionary> + { + {"icon", c.ContentType.Icon.Yield()}, + {UmbracoExamineIndexer.PublishedFieldName, new object[] {c.Published ? 1 : 0}}, //Always add invariant published value + {"id", new object[] {c.Id}}, + {"key", new object[] {c.Key}}, + {"parentID", new object[] {c.Level > 1 ? c.ParentId : -1}}, + {"level", new object[] {c.Level}}, + {"creatorID", new object[] {c.CreatorId}}, + {"sortOrder", new object[] {c.SortOrder}}, + {"createDate", new object[] {c.CreateDate}}, //Always add invariant createDate + {"updateDate", new object[] {c.UpdateDate}}, //Always add invariant updateDate + {"nodeName", PublishedValuesOnly //Always add invariant nodeName + ? c.PublishName.Yield() + : c.Name.Yield()}, + {"urlName", urlValue.Yield()}, //Always add invariant urlName + {"path", c.Path.Yield()}, + {"nodeType", new object[] {c.ContentType.Id}}, + {"creatorName", (c.GetCreatorProfile(_userService)?.Name ?? "??").Yield() }, + {"writerName",(c.GetWriterProfile(_userService)?.Name ?? "??").Yield() }, + {"writerID", new object[] {c.WriterId}}, + {"template", new object[] {c.Template?.Id ?? 0}}, + {UmbracoContentIndexer.VariesByCultureFieldName, new object[] {0}}, + }; + + if (isVariant) + { + values[UmbracoContentIndexer.VariesByCultureFieldName] = new object[] { 1 }; + + foreach (var culture in c.AvailableCultures) + { + var variantUrl = c.GetUrlSegment(_urlSegmentProviders, culture); + var lowerCulture = culture.ToLowerInvariant(); + values[$"urlName_{lowerCulture}"] = variantUrl.Yield(); + values[$"nodeName_{lowerCulture}"] = PublishedValuesOnly + ? c.GetPublishName(culture).Yield() + : c.GetCultureName(culture).Yield(); + values[$"{UmbracoExamineIndexer.PublishedFieldName}_{lowerCulture}"] = (c.IsCulturePublished(culture) ? 1 : 0).Yield(); + values[$"updateDate_{lowerCulture}"] = PublishedValuesOnly + ? c.GetPublishDate(culture).Yield() + : c.GetUpdateDate(culture).Yield(); + } + } + + foreach (var property in c.Properties) + { + if (!property.PropertyType.VariesByCulture()) + { + AddPropertyValue(property, null, null, values); + } + else + { + foreach (var culture in c.AvailableCultures) + AddPropertyValue(property, culture.ToLowerInvariant(), null, values); + } + } + + var vs = new ValueSet(c.Id.ToInvariantString(), IndexTypes.Content, c.ContentType.Alias, values); + + yield return vs; + } + } + } + +} diff --git a/src/Umbraco.Examine/ContentValueSetValidator.cs b/src/Umbraco.Examine/ContentValueSetValidator.cs new file mode 100644 index 0000000000..eabf15f672 --- /dev/null +++ b/src/Umbraco.Examine/ContentValueSetValidator.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Examine; +using Examine.LuceneEngine.Providers; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.Services; + +namespace Umbraco.Examine +{ + /// + /// Used to validate a ValueSet for content/media - based on permissions, parent id, etc.... + /// + public class ContentValueSetValidator : ValueSetValidator, IContentValueSetValidator + { + private readonly IPublicAccessService _publicAccessService; + + private const string PathKey = "path"; + private static readonly IEnumerable ValidCategories = new[] {IndexTypes.Content, IndexTypes.Media}; + protected override IEnumerable ValidIndexCategories => ValidCategories; + + public bool PublishedValuesOnly { get; } + public bool SupportProtectedContent { get; } + public int? ParentId { get; } + + public bool ValidatePath(string path, string category) + { + //check if this document is a descendent of the parent + if (ParentId.HasValue && ParentId.Value > 0) + { + // we cannot return FAILED here because we need the value set to get into the indexer and then deal with it from there + // because we need to remove anything that doesn't pass by parent Id in the cases that umbraco data is moved to an illegal parent. + if (!path.Contains(string.Concat(",", ParentId.Value, ","))) + return false; + } + + return true; + } + + public bool ValidateRecycleBin(string path, string category) + { + var recycleBinId = category == IndexTypes.Content ? Constants.System.RecycleBinContent : Constants.System.RecycleBinMedia; + + //check for recycle bin + if (PublishedValuesOnly) + { + if (path.Contains(string.Concat(",", recycleBinId, ","))) + return false; + } + return true; + } + + public bool ValidateProtectedContent(string path, string category) + { + if (category == IndexTypes.Content + && !SupportProtectedContent + //if the service is null we can't look this up so we'll return false + && (_publicAccessService == null || _publicAccessService.IsProtected(path))) + { + return false; + } + + return true; + } + + public ContentValueSetValidator(bool publishedValuesOnly, int? parentId = null, + IEnumerable includeItemTypes = null, IEnumerable excludeItemTypes = null) + : this(publishedValuesOnly, true, null, parentId, includeItemTypes, excludeItemTypes) + { + } + + public ContentValueSetValidator(bool publishedValuesOnly, bool supportProtectedContent, + IPublicAccessService publicAccessService, int? parentId = null, + IEnumerable includeItemTypes = null, IEnumerable excludeItemTypes = null) + : base(includeItemTypes, excludeItemTypes, null, null) + { + PublishedValuesOnly = publishedValuesOnly; + SupportProtectedContent = supportProtectedContent; + ParentId = parentId; + _publicAccessService = publicAccessService; + } + + public override ValueSetValidationResult Validate(ValueSet valueSet) + { + var baseValidate = base.Validate(valueSet); + if (baseValidate == ValueSetValidationResult.Failed) + return ValueSetValidationResult.Failed; + + var isFiltered = baseValidate == ValueSetValidationResult.Filtered; + + //check for published content + if (valueSet.Category == IndexTypes.Content && PublishedValuesOnly) + { + if (!valueSet.Values.TryGetValue(UmbracoExamineIndexer.PublishedFieldName, out var published)) + return ValueSetValidationResult.Failed; + + if (!published[0].Equals(1)) + return ValueSetValidationResult.Failed; + + //deal with variants, if there are unpublished variants than we need to remove them from the value set + if (valueSet.Values.TryGetValue(UmbracoContentIndexer.VariesByCultureFieldName, out var variesByCulture) + && variesByCulture.Count > 0 && variesByCulture[0].Equals(1)) + { + //so this valueset is for a content that varies by culture, now check for non-published cultures and remove those values + foreach(var publishField in valueSet.Values.Where(x => x.Key.StartsWith($"{UmbracoExamineIndexer.PublishedFieldName}_")).ToList()) + { + if (publishField.Value.Count <= 0 || !publishField.Value[0].Equals(1)) + { + //this culture is not published, so remove all of these culture values + var cultureSuffix = publishField.Key.Substring(publishField.Key.LastIndexOf('_')); + foreach (var cultureField in valueSet.Values.Where(x => x.Key.InvariantEndsWith(cultureSuffix)).ToList()) + { + valueSet.Values.Remove(cultureField.Key); + isFiltered = true; + } + } + } + } + } + + //must have a 'path' + if (!valueSet.Values.TryGetValue(PathKey, out var pathValues)) return ValueSetValidationResult.Failed; + if (pathValues.Count == 0) return ValueSetValidationResult.Failed; + if (pathValues[0] == null) return ValueSetValidationResult.Failed; + if (pathValues[0].ToString().IsNullOrWhiteSpace()) return ValueSetValidationResult.Failed; + var path = pathValues[0].ToString(); + + // We need to validate the path of the content based on ParentId, protected content and recycle bin rules. + // We cannot return FAILED here because we need the value set to get into the indexer and then deal with it from there + // because we need to remove anything that doesn't pass by protected content in the cases that umbraco data is moved to an illegal parent. + if (!ValidatePath(path, valueSet.Category) + || !ValidateRecycleBin(path, valueSet.Category) + || !ValidateProtectedContent(path, valueSet.Category)) + return ValueSetValidationResult.Filtered; + + return isFiltered ? ValueSetValidationResult.Filtered: ValueSetValidationResult.Valid; + } + } +} diff --git a/src/Umbraco.Examine/ExamineExtensions.cs b/src/Umbraco.Examine/ExamineExtensions.cs new file mode 100644 index 0000000000..3681979267 --- /dev/null +++ b/src/Umbraco.Examine/ExamineExtensions.cs @@ -0,0 +1,72 @@ +using System; +using Examine.LuceneEngine.Providers; +using Lucene.Net.Index; +using Lucene.Net.Search; +using Lucene.Net.Store; + +namespace Umbraco.Examine +{ + /// + /// Extension methods for the LuceneIndex + /// + internal static class ExamineExtensions + { + /// + /// Checks if the index can be read/opened + /// + /// + /// The exception returned if there was an error + /// + public static bool IsHealthy(this LuceneIndex indexer, out Exception ex) + { + try + { + using (indexer.GetIndexWriter().GetReader()) + { + ex = null; + return true; + } + } + catch (Exception e) + { + ex = e; + return false; + } + } + + /// + /// Return the number of indexed documents in Lucene + /// + /// + /// + public static int GetIndexDocumentCount(this LuceneIndex indexer) + { + if (!((indexer.GetSearcher() as LuceneSearcher)?.GetLuceneSearcher() is IndexSearcher searcher)) + return 0; + + using (searcher) + using (var reader = searcher.IndexReader) + { + return reader.NumDocs(); + } + } + + /// + /// Return the total number of fields in the index + /// + /// + /// + public static int GetIndexFieldCount(this LuceneIndex indexer) + { + if (!((indexer.GetSearcher() as LuceneSearcher)?.GetLuceneSearcher() is IndexSearcher searcher)) + return 0; + + using (searcher) + using (var reader = searcher.IndexReader) + { + return reader.GetFieldNames(IndexReader.FieldOption.ALL).Count; + } + } + + } +} diff --git a/src/Umbraco.Examine/IContentValueSetBuilder.cs b/src/Umbraco.Examine/IContentValueSetBuilder.cs new file mode 100644 index 0000000000..fed706d592 --- /dev/null +++ b/src/Umbraco.Examine/IContentValueSetBuilder.cs @@ -0,0 +1,13 @@ +using Examine; +using Umbraco.Core.Models; + +namespace Umbraco.Examine +{ + /// + /// + /// Marker interface for a builder for supporting unpublished content + /// + public interface IContentValueSetBuilder : IValueSetBuilder + { + } +} diff --git a/src/Umbraco.Examine/IContentValueSetValidator.cs b/src/Umbraco.Examine/IContentValueSetValidator.cs new file mode 100644 index 0000000000..fa85a0d32b --- /dev/null +++ b/src/Umbraco.Examine/IContentValueSetValidator.cs @@ -0,0 +1,31 @@ +using Examine; + +namespace Umbraco.Examine +{ + /// + /// An extended for content indexes + /// + public interface IContentValueSetValidator : IValueSetValidator + { + /// + /// When set to true the index will only retain published values + /// + /// + /// Any non-published values will not be put or kept in the index: + /// * Deleted, Trashed, non-published Content items + /// * non-published Variants + /// + bool PublishedValuesOnly { get; } + + /// + /// If true, protected content will be indexed otherwise it will not be put or kept in the index + /// + bool SupportProtectedContent { get; } + + int? ParentId { get; } + + bool ValidatePath(string path, string category); + bool ValidateRecycleBin(string path, string category); + bool ValidateProtectedContent(string path, string category); + } +} diff --git a/src/Umbraco.Examine/IIndexDiagnostics.cs b/src/Umbraco.Examine/IIndexDiagnostics.cs new file mode 100644 index 0000000000..04ca4a6ab9 --- /dev/null +++ b/src/Umbraco.Examine/IIndexDiagnostics.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using Examine; +using Umbraco.Core; + +namespace Umbraco.Examine +{ + + + /// + /// Exposes diagnostic information about an index + /// + public interface IIndexDiagnostics + { + /// + /// The number of documents in the index + /// + int DocumentCount { get; } + + /// + /// The number of fields in the index + /// + int FieldCount { get; } + + /// + /// If the index can be open/read + /// + /// + /// A successful attempt if it is healthy, else a failed attempt with a message if unhealthy + /// + Attempt IsHealthy(); + + /// + /// A key/value collection of diagnostic properties for the index + /// + /// + /// Used to display in the UI + /// + IReadOnlyDictionary Metadata { get; } + } +} diff --git a/src/Umbraco.Examine/IIndexPopulator.cs b/src/Umbraco.Examine/IIndexPopulator.cs new file mode 100644 index 0000000000..aeb3514578 --- /dev/null +++ b/src/Umbraco.Examine/IIndexPopulator.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using Examine; + +namespace Umbraco.Examine +{ + + + public interface IIndexPopulator + { + bool IsRegistered(string indexName); + void RegisterIndex(string indexName); + + /// + /// Populate indexers + /// + /// + void Populate(params IIndex[] indexes); + } + +} diff --git a/src/Umbraco.Examine/IPublishedContentValueSetBuilder.cs b/src/Umbraco.Examine/IPublishedContentValueSetBuilder.cs new file mode 100644 index 0000000000..c337a7a1e6 --- /dev/null +++ b/src/Umbraco.Examine/IPublishedContentValueSetBuilder.cs @@ -0,0 +1,12 @@ +using Examine; +using Umbraco.Core.Models; + +namespace Umbraco.Examine +{ + /// + /// Marker interface for a builder for only published content + /// + public interface IPublishedContentValueSetBuilder : IValueSetBuilder + { + } +} \ No newline at end of file diff --git a/src/Umbraco.Examine/IUmbracoIndexer.cs b/src/Umbraco.Examine/IUmbracoIndexer.cs new file mode 100644 index 0000000000..00f772b1e2 --- /dev/null +++ b/src/Umbraco.Examine/IUmbracoIndexer.cs @@ -0,0 +1,25 @@ +using Examine; + +namespace Umbraco.Examine +{ + /// + /// A Marker interface for defining an Umbraco indexer + /// + public interface IUmbracoIndexer : IIndex + { + /// + /// When set to true Umbraco will keep the index in sync with Umbraco data automatically + /// + bool EnableDefaultEventHandler { get; } + + /// + /// When set to true the index will only retain published values + /// + /// + /// Any non-published values will not be put or kept in the index: + /// * Deleted, Trashed, non-published Content items + /// * non-published Variants + /// + bool PublishedValuesOnly { get; } + } +} diff --git a/src/Umbraco.Examine/IValueSetBuilder.cs b/src/Umbraco.Examine/IValueSetBuilder.cs new file mode 100644 index 0000000000..89aa907926 --- /dev/null +++ b/src/Umbraco.Examine/IValueSetBuilder.cs @@ -0,0 +1,22 @@ +using Examine; +using System.Collections.Generic; +using Umbraco.Core.Models; + +namespace Umbraco.Examine +{ + /// + /// Creates a collection of to be indexed based on a collection of + /// + /// + public interface IValueSetBuilder + where TContent : IContentBase + { + /// + /// Creates a collection of to be indexed based on a collection of + /// + /// + /// + IEnumerable GetValueSets(params TContent[] content); + } + +} diff --git a/src/Umbraco.Examine/IndexPopulator.cs b/src/Umbraco.Examine/IndexPopulator.cs new file mode 100644 index 0000000000..5f701312ea --- /dev/null +++ b/src/Umbraco.Examine/IndexPopulator.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Linq; +using Examine; +using Umbraco.Core.Collections; + +namespace Umbraco.Examine +{ + public abstract class IndexPopulator : IIndexPopulator + { + private readonly ConcurrentHashSet _registeredIndexes = new ConcurrentHashSet(); + + public bool IsRegistered(string indexName) + { + return _registeredIndexes.Contains(indexName); + } + + /// + /// Registers an index for this populator + /// + /// + public void RegisterIndex(string indexName) + { + _registeredIndexes.Add(indexName); + } + + public void Populate(params IIndex[] indexes) + { + PopulateIndexes(indexes.Where(x => IsRegistered(x.Name))); + } + + protected abstract void PopulateIndexes(IEnumerable indexes); + } +} diff --git a/src/Umbraco.Examine/IndexRebuilder.cs b/src/Umbraco.Examine/IndexRebuilder.cs new file mode 100644 index 0000000000..39b29c5a2b --- /dev/null +++ b/src/Umbraco.Examine/IndexRebuilder.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Examine; + +namespace Umbraco.Examine +{ + /// + /// Utility to rebuild all indexes ensuring minimal data queries + /// + public class IndexRebuilder + { + private readonly IEnumerable _populators; + public IExamineManager ExamineManager { get; } + + public IndexRebuilder(IExamineManager examineManager, IEnumerable populators) + { + _populators = populators; + ExamineManager = examineManager; + } + + public bool CanRebuild(string indexName) + { + return _populators.Any(x => x.IsRegistered(indexName)); + } + + public void RebuildIndex(string indexName) + { + if (!ExamineManager.TryGetIndex(indexName, out var index)) + throw new InvalidOperationException($"No index found with name {indexName}"); + index.CreateIndex(); // clear the index + foreach (var populator in _populators) + { + populator.Populate(index); + } + } + + public void RebuildIndexes(bool onlyEmptyIndexes) + { + var indexes = (onlyEmptyIndexes + ? ExamineManager.Indexes.Where(x => !x.IndexExists()) + : ExamineManager.Indexes).ToArray(); + + foreach (var index in indexes) + { + index.CreateIndex(); // clear the index + } + + //run the populators in parallel against all indexes + Parallel.ForEach(_populators, populator => populator.Populate(indexes)); + } + + } +} diff --git a/src/Umbraco.Examine/IndexTypes.cs b/src/Umbraco.Examine/IndexTypes.cs index fab72eca25..3fa00e234c 100644 --- a/src/Umbraco.Examine/IndexTypes.cs +++ b/src/Umbraco.Examine/IndexTypes.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Lucene.Net.Store; - -namespace Umbraco.Examine +namespace Umbraco.Examine { /// /// The index types stored in the Lucene Index diff --git a/src/Umbraco.Examine/MediaIndexPopulator.cs b/src/Umbraco.Examine/MediaIndexPopulator.cs new file mode 100644 index 0000000000..39a0b3f7c8 --- /dev/null +++ b/src/Umbraco.Examine/MediaIndexPopulator.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; +using System.Linq; +using Examine; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.Services; + +namespace Umbraco.Examine +{ + /// + /// Performs the data lookups required to rebuild a media index + /// + public class MediaIndexPopulator : IndexPopulator + { + private readonly int? _parentId; + private readonly IMediaService _mediaService; + private readonly IValueSetBuilder _mediaValueSetBuilder; + + /// + /// Default constructor to lookup all content data + /// + /// + /// + public MediaIndexPopulator(IMediaService mediaService, IValueSetBuilder mediaValueSetBuilder) + : this(null, mediaService, mediaValueSetBuilder) + { + } + + /// + /// Optional constructor allowing specifying custom query parameters + /// + /// + /// + /// + public MediaIndexPopulator(int? parentId, IMediaService mediaService, IValueSetBuilder mediaValueSetBuilder) + { + _parentId = parentId; + _mediaService = mediaService; + _mediaValueSetBuilder = mediaValueSetBuilder; + + RegisterIndex(Constants.UmbracoIndexes.InternalIndexName); + RegisterIndex(Constants.UmbracoIndexes.ExternalIndexName); + } + + protected override void PopulateIndexes(IEnumerable indexes) + { + const int pageSize = 10000; + var pageIndex = 0; + + var mediaParentId = -1; + + if (_parentId.HasValue && _parentId.Value > 0) + { + mediaParentId = _parentId.Value; + } + + IMedia[] media; + + do + { + media = _mediaService.GetPagedDescendants(mediaParentId, pageIndex, pageSize, out var total).ToArray(); + + if (media.Length > 0) + { + // ReSharper disable once PossibleMultipleEnumeration + foreach (var index in indexes) + index.IndexItems(_mediaValueSetBuilder.GetValueSets(media)); + } + + pageIndex++; + } while (media.Length == pageSize); + } + + } +} diff --git a/src/Umbraco.Examine/MediaValueSetBuilder.cs b/src/Umbraco.Examine/MediaValueSetBuilder.cs new file mode 100644 index 0000000000..8df51570c1 --- /dev/null +++ b/src/Umbraco.Examine/MediaValueSetBuilder.cs @@ -0,0 +1,61 @@ +using Examine; +using System.Collections.Generic; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; +using Umbraco.Core.Strings; + +namespace Umbraco.Examine +{ + public class MediaValueSetBuilder : BaseValueSetBuilder + { + private readonly IEnumerable _urlSegmentProviders; + private readonly IUserService _userService; + + public MediaValueSetBuilder(PropertyEditorCollection propertyEditors, + IEnumerable urlSegmentProviders, + IUserService userService) + : base(propertyEditors, false) + { + _urlSegmentProviders = urlSegmentProviders; + _userService = userService; + } + + /// + public override IEnumerable GetValueSets(params IMedia[] media) + { + foreach (var m in media) + { + var urlValue = m.GetUrlSegment(_urlSegmentProviders); + var values = new Dictionary> + { + {"icon", m.ContentType.Icon.Yield()}, + {"id", new object[] {m.Id}}, + {"key", new object[] {m.Key}}, + {"parentID", new object[] {m.Level > 1 ? m.ParentId : -1}}, + {"level", new object[] {m.Level}}, + {"creatorID", new object[] {m.CreatorId}}, + {"sortOrder", new object[] {m.SortOrder}}, + {"createDate", new object[] {m.CreateDate}}, + {"updateDate", new object[] {m.UpdateDate}}, + {"nodeName", m.Name.Yield()}, + {"urlName", urlValue.Yield()}, + {"path", m.Path.Yield()}, + {"nodeType", new object[] {m.ContentType.Id}}, + {"creatorName", m.GetCreatorProfile(_userService).Name.Yield()} + }; + + foreach (var property in m.Properties) + { + AddPropertyValue(property, null, null, values); + } + + var vs = new ValueSet(m.Id.ToInvariantString(), IndexTypes.Media, m.ContentType.Alias, values); + + yield return vs; + } + } + } + +} diff --git a/src/Umbraco.Examine/MemberIndexPopulator.cs b/src/Umbraco.Examine/MemberIndexPopulator.cs new file mode 100644 index 0000000000..cf04861372 --- /dev/null +++ b/src/Umbraco.Examine/MemberIndexPopulator.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Linq; +using Examine; +using Lucene.Net.Util; +using Umbraco.Core.Models; +using Umbraco.Core.Services; + +namespace Umbraco.Examine +{ + public class MemberIndexPopulator : IndexPopulator + { + private readonly IMemberService _memberService; + private readonly IValueSetBuilder _valueSetBuilder; + + public MemberIndexPopulator(IMemberService memberService, IValueSetBuilder valueSetBuilder) + { + _memberService = memberService; + _valueSetBuilder = valueSetBuilder; + + RegisterIndex(Core.Constants.UmbracoIndexes.MembersIndexName); + } + protected override void PopulateIndexes(IEnumerable indexes) + { + const int pageSize = 1000; + var pageIndex = 0; + + IMember[] members; + + //no node types specified, do all members + do + { + members = _memberService.GetAll(pageIndex, pageSize, out _).ToArray(); + + if (members.Length > 0) + { + // ReSharper disable once PossibleMultipleEnumeration + foreach (var index in indexes) + index.IndexItems(_valueSetBuilder.GetValueSets(members)); + } + + pageIndex++; + } while (members.Length == pageSize); + } + } +} diff --git a/src/Umbraco.Examine/MemberValueSetBuilder.cs b/src/Umbraco.Examine/MemberValueSetBuilder.cs new file mode 100644 index 0000000000..9864aba18d --- /dev/null +++ b/src/Umbraco.Examine/MemberValueSetBuilder.cs @@ -0,0 +1,52 @@ +using Examine; +using System.Collections.Generic; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Examine +{ + + public class MemberValueSetBuilder : BaseValueSetBuilder + { + public MemberValueSetBuilder(PropertyEditorCollection propertyEditors) + : base(propertyEditors, false) + { + } + + /// + public override IEnumerable GetValueSets(params IMember[] members) + { + foreach (var m in members) + { + var values = new Dictionary> + { + {"icon", m.ContentType.Icon.Yield()}, + {"id", new object[] {m.Id}}, + {"key", new object[] {m.Key}}, + {"parentID", new object[] {m.Level > 1 ? m.ParentId : -1}}, + {"level", new object[] {m.Level}}, + {"creatorID", new object[] {m.CreatorId}}, + {"sortOrder", new object[] {m.SortOrder}}, + {"createDate", new object[] {m.CreateDate}}, + {"updateDate", new object[] {m.UpdateDate}}, + {"nodeName", m.Name.Yield()}, + {"path", m.Path.Yield()}, + {"nodeType", new object[] {m.ContentType.Id}}, + {"loginName", m.Username.Yield()}, + {"email", m.Email.Yield()}, + }; + + foreach (var property in m.Properties) + { + AddPropertyValue(property, null, null, values); + } + + var vs = new ValueSet(m.Id.ToInvariantString(), IndexTypes.Member, m.ContentType.Alias, values); + + yield return vs; + } + } + } + +} diff --git a/src/Umbraco.Examine/MemberValueSetValidator.cs b/src/Umbraco.Examine/MemberValueSetValidator.cs new file mode 100644 index 0000000000..71de6001ce --- /dev/null +++ b/src/Umbraco.Examine/MemberValueSetValidator.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Linq; +using Examine; + +namespace Umbraco.Examine +{ + public class MemberValueSetValidator : ValueSetValidator + { + public MemberValueSetValidator() : base(null, null, DefaultMemberIndexFields, null) + { + } + + public MemberValueSetValidator(IEnumerable includeItemTypes, IEnumerable excludeItemTypes) + : base(includeItemTypes, excludeItemTypes, DefaultMemberIndexFields, null) + { + } + + public MemberValueSetValidator(IEnumerable includeItemTypes, IEnumerable excludeItemTypes, IEnumerable includeFields, IEnumerable excludeFields) + : base(includeItemTypes, excludeItemTypes, includeFields, excludeFields) + { + } + + /// + /// By default these are the member fields we index + /// + public static readonly string[] DefaultMemberIndexFields = { "id", "nodeName", "updateDate", "loginName", "email" }; + + private static readonly IEnumerable ValidCategories = new[] { IndexTypes.Member }; + protected override IEnumerable ValidIndexCategories => ValidCategories; + + } +} diff --git a/src/Umbraco.Examine/PublishedContentIndexPopulator.cs b/src/Umbraco.Examine/PublishedContentIndexPopulator.cs new file mode 100644 index 0000000000..143e2db630 --- /dev/null +++ b/src/Umbraco.Examine/PublishedContentIndexPopulator.cs @@ -0,0 +1,22 @@ +using Umbraco.Core.Models; +using Umbraco.Core.Services; +using Umbraco.Core.Persistence; + +namespace Umbraco.Examine +{ + /// + /// Performs the data lookups required to rebuild a content index containing only published content + /// + /// + /// The published (external) index will still rebuild just fine using the default which is what + /// is used when rebuilding all indexes, but this will be used when the single index is rebuilt and will go a little bit faster + /// since the data query is more specific. + /// + public class PublishedContentIndexPopulator : ContentIndexPopulator + { + public PublishedContentIndexPopulator(IContentService contentService, ISqlContext sqlContext, IPublishedContentValueSetBuilder contentValueSetBuilder) : + base(true, null, contentService, sqlContext, contentValueSetBuilder) + { + } + } +} diff --git a/src/Umbraco.Examine/Umbraco.Examine.csproj b/src/Umbraco.Examine/Umbraco.Examine.csproj index 678ae124d2..9194d8332d 100644 --- a/src/Umbraco.Examine/Umbraco.Examine.csproj +++ b/src/Umbraco.Examine/Umbraco.Examine.csproj @@ -48,30 +48,51 @@ - + + + + + + + + + + + + + + + + + + + + + - - + + Properties\SolutionInfo.cs + diff --git a/src/Umbraco.Examine/UmbracoContentIndexer.cs b/src/Umbraco.Examine/UmbracoContentIndexer.cs index fab9f226a4..0501fe90c6 100644 --- a/src/Umbraco.Examine/UmbracoContentIndexer.cs +++ b/src/Umbraco.Examine/UmbracoContentIndexer.cs @@ -5,7 +5,6 @@ using System.ComponentModel; using System.Linq; using Examine; using Umbraco.Core; -using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Examine.LuceneEngine.Indexing; @@ -14,14 +13,8 @@ using Lucene.Net.Analysis; using Lucene.Net.Store; using Umbraco.Core.Composing; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; -using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Scoping; using Umbraco.Examine.Config; -using IContentService = Umbraco.Core.Services.IContentService; -using IMediaService = Umbraco.Core.Services.IMediaService; - +using Examine.LuceneEngine; namespace Umbraco.Examine { @@ -30,12 +23,8 @@ namespace Umbraco.Examine /// public class UmbracoContentIndexer : UmbracoExamineIndexer { - protected IContentService ContentService { get; } - protected IMediaService MediaService { get; } - protected IUserService UserService { get; } - - private readonly IEnumerable _urlSegmentProviders; - private int? _parentId; + public const string VariesByCultureFieldName = SpecialFieldPrefix + "VariesByCulture"; + protected ILocalizationService LanguageService { get; } #region Constructors @@ -45,13 +34,9 @@ namespace Umbraco.Examine [EditorBrowsable(EditorBrowsableState.Never)] public UmbracoContentIndexer() { - ContentService = Current.Services.ContentService; - MediaService = Current.Services.MediaService; - UserService = Current.Services.UserService; + LanguageService = Current.Services.LocalizationService; - _urlSegmentProviders = Current.UrlSegmentProviders; - - InitializeQueries(Current.SqlContext); + //note: The validator for this config based indexer is set in the Initialize method } /// @@ -62,13 +47,8 @@ namespace Umbraco.Examine /// /// /// - /// - /// - /// - /// - /// + /// /// - /// /// public UmbracoContentIndexer( string name, @@ -76,36 +56,16 @@ namespace Umbraco.Examine Directory luceneDirectory, Analyzer defaultAnalyzer, ProfilingLogger profilingLogger, - IContentService contentService, - IMediaService mediaService, - IUserService userService, - ISqlContext sqlContext, - IEnumerable urlSegmentProviders, - IValueSetValidator validator, - UmbracoContentIndexerOptions options, + ILocalizationService languageService, + IContentValueSetValidator validator, IReadOnlyDictionary> indexValueTypes = null) : base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, profilingLogger, validator, indexValueTypes) { if (validator == null) throw new ArgumentNullException(nameof(validator)); - if (options == null) throw new ArgumentNullException(nameof(options)); + LanguageService = languageService ?? throw new ArgumentNullException(nameof(languageService)); - SupportProtectedContent = options.SupportProtectedContent; - SupportUnpublishedContent = options.SupportUnpublishedContent; - ParentId = options.ParentId; - - ContentService = contentService ?? throw new ArgumentNullException(nameof(contentService)); - MediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); - UserService = userService ?? throw new ArgumentNullException(nameof(userService)); - _urlSegmentProviders = urlSegmentProviders ?? throw new ArgumentNullException(nameof(urlSegmentProviders)); - - InitializeQueries(sqlContext); - } - - private void InitializeQueries(ISqlContext sqlContext) - { - if (sqlContext == null) throw new ArgumentNullException(nameof(sqlContext)); - if (_publishedQuery == null) - _publishedQuery = sqlContext.Query().Where(x => x.Published); + if (validator is IContentValueSetValidator contentValueSetValidator) + PublishedValuesOnly = contentValueSetValidator.PublishedValuesOnly; } #endregion @@ -129,25 +89,24 @@ namespace Umbraco.Examine /// /// An attempt is made to call on a provider after the provider has already been initialized. /// - + [EditorBrowsable(EditorBrowsableState.Never)] public override void Initialize(string name, NameValueCollection config) { + base.Initialize(name, config); + + var supportUnpublished = false; + var supportProtected = false; + //check if there's a flag specifying to support unpublished content, //if not, set to false; - if (config["supportUnpublished"] != null && bool.TryParse(config["supportUnpublished"], out var supportUnpublished)) - SupportUnpublishedContent = supportUnpublished; - else - SupportUnpublishedContent = false; - + if (config["supportUnpublished"] != null) + bool.TryParse(config["supportUnpublished"], out supportUnpublished); //check if there's a flag specifying to support protected content, //if not, set to false; - if (config["supportProtected"] != null && bool.TryParse(config["supportProtected"], out var supportProtected)) - SupportProtectedContent = supportProtected; - else - SupportProtectedContent = false; + if (config["supportProtected"] != null) + bool.TryParse(config["supportProtected"], out supportProtected); - base.Initialize(name, config); //now we need to build up the indexer options so we can create our validator int? parentId = null; @@ -156,44 +115,76 @@ namespace Umbraco.Examine var indexSet = IndexSets.Instance.Sets[IndexSetName]; parentId = indexSet.IndexParentId; } - ValueSetValidator = new UmbracoContentValueSetValidator( - new UmbracoContentIndexerOptions(SupportUnpublishedContent, SupportProtectedContent, parentId), + + ValueSetValidator = new ContentValueSetValidator( + supportUnpublished, supportProtected, //Using a singleton here, we can't inject this when using config based providers and we don't use this //anywhere else in this class - Current.Services.PublicAccessService); + Current.Services.PublicAccessService, + parentId, + ConfigIndexCriteria.IncludeItemTypes, ConfigIndexCriteria.ExcludeItemTypes); + + PublishedValuesOnly = supportUnpublished; } #endregion - #region Properties - /// - /// By default this is false, if set to true then the indexer will include indexing content that is flagged as publicly protected. - /// This property is ignored if SupportUnpublishedContent is set to true. + /// Special check for invalid paths /// - public bool SupportProtectedContent { get; protected set; } - - /// - /// Determines if the manager will call the indexing methods when content is saved or deleted as - /// opposed to cache being updated. - /// - public bool SupportUnpublishedContent { get; protected set; } - - /// - /// If set this will filter the content items allowed to be indexed - /// - public int? ParentId + /// + /// + protected override void PerformIndexItems(IEnumerable values, Action onComplete) { - get => _parentId ?? ConfigIndexCriteria?.ParentNodeId; - protected set => _parentId = value; + //We don't want to re-enumerate this list, but we need to split it into 2x enumerables: invalid and valid items. + // The Invalid items will be deleted, these are items that have invalid paths (i.e. moved to the recycle bin, etc...) + // Then we'll index the Value group all together. + // We return 0 or 1 here so we can order the results and do the invalid first and then the valid. + var invalidOrValid = values.GroupBy(v => + { + if (!v.Values.TryGetValue("path", out var paths) || paths.Count <= 0 || paths[0] == null) + return 0; + + //we know this is an IContentValueSetValidator + var validator = (IContentValueSetValidator)ValueSetValidator; + var path = paths[0].ToString(); + + return (!validator.ValidatePath(path, v.Category) + || !validator.ValidateRecycleBin(path, v.Category) + || !validator.ValidateProtectedContent(path, v.Category)) + ? 0 + : 1; + }); + + var hasDeletes = false; + var hasUpdates = false; + foreach (var group in invalidOrValid.OrderBy(x => x.Key)) + { + if (group.Key == 0) + { + hasDeletes = true; + //these are the invalid items so we'll delete them + //since the path is not valid we need to delete this item in case it exists in the index already and has now + //been moved to an invalid parent. + foreach (var i in group) + QueueIndexOperation(new IndexOperation(new ValueSet(i.Id), IndexOperationType.Delete)); + } + else + { + hasUpdates = true; + //these are the valid ones, so just index them all at once + base.PerformIndexItems(group, onComplete); + } + } + + if (hasDeletes && !hasUpdates || !hasDeletes && !hasUpdates) + { + //we need to manually call the completed method + onComplete(new IndexOperationEventArgs(this, 0)); + } } - protected override IEnumerable SupportedTypes => new[] {IndexTypes.Content, IndexTypes.Media}; - - #endregion - - #region Public methods - + /// /// /// Deletes a node from the index. /// @@ -202,7 +193,8 @@ namespace Umbraco.Examine /// custom Lucene search to find all decendents and create Delete item queues for them too. /// /// ID of the node to delete - public override void DeleteFromIndex(string nodeId) + /// + protected override void PerformDeleteFromIndex(string nodeId, Action onComplete) { //find all descendants based on path var descendantPath = $@"\-1\,*{nodeId}\,*"; @@ -217,204 +209,32 @@ namespace Umbraco.Examine //need to queue a delete item for each one found foreach (var r in results) { - QueueIndexOperation(new IndexOperation(IndexItem.ForId(r.Id), IndexOperationType.Delete)); + QueueIndexOperation(new IndexOperation(new ValueSet(r.Id), IndexOperationType.Delete)); } - base.DeleteFromIndex(nodeId); + base.PerformDeleteFromIndex(nodeId, onComplete); } - #endregion - - #region Protected /// - /// This is a static query, it's parameters don't change so store statically + /// Overridden to ensure that the variant system fields have the right value types /// - private static IQuery _publishedQuery; - - protected override void PerformIndexAll(string type) + /// + /// + /// + protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary> indexValueTypesFactory = null) { - const int pageSize = 10000; - var pageIndex = 0; - - switch (type) + //fixme: languages are dynamic so although this will work on startup it wont work when languages are edited + foreach(var lang in LanguageService.GetAllLanguages()) { - case IndexTypes.Content: - var contentParentId = -1; - if (ParentId.HasValue && ParentId.Value > 0) - { - contentParentId = ParentId.Value; - } - IContent[] content; - - do - { - long total; - - IEnumerable descendants; - if (SupportUnpublishedContent) - { - descendants = ContentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out total); - } - else - { - //add the published filter - descendants = ContentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out total, - _publishedQuery, Ordering.By("Path", Direction.Ascending)); - } - - //if specific types are declared we need to post filter them - //TODO: Update the service layer to join the cmsContentType table so we can query by content type too - if (ConfigIndexCriteria != null && ConfigIndexCriteria.IncludeItemTypes.Any()) - { - content = descendants.Where(x => ConfigIndexCriteria.IncludeItemTypes.Contains(x.ContentType.Alias)).ToArray(); - } - else - { - content = descendants.ToArray(); - } - - IndexItems(GetValueSets(_urlSegmentProviders, UserService, content)); - - pageIndex++; - } while (content.Length == pageSize); - - break; - case IndexTypes.Media: - var mediaParentId = -1; - - if (ParentId.HasValue && ParentId.Value > 0) - { - mediaParentId = ParentId.Value; - } - - // merge note: 7.5 changes this to use mediaService.GetPagedXmlEntries but we cannot merge the - // change here as mediaService does not provide access to Xml in v8 - and actually Examine should - // not assume that Umbraco provides Xml at all. - - IMedia[] media; - - do - { - var descendants = MediaService.GetPagedDescendants(mediaParentId, pageIndex, pageSize, out _); - - //if specific types are declared we need to post filter them - //TODO: Update the service layer to join the cmsContentType table so we can query by content type too - if (ConfigIndexCriteria != null && ConfigIndexCriteria.IncludeItemTypes.Any()) - { - media = descendants.Where(x => ConfigIndexCriteria.IncludeItemTypes.Contains(x.ContentType.Alias)).ToArray(); - } - else - { - media = descendants.ToArray(); - } - - IndexItems(GetValueSets(_urlSegmentProviders, UserService, media)); - - pageIndex++; - } while (media.Length == pageSize); - - break; - } - } - - public static IEnumerable GetValueSets(IEnumerable urlSegmentProviders, IUserService userService, params IContent[] content) - { - foreach (var c in content) - { - var urlValue = c.GetUrlSegment(urlSegmentProviders); // for now, index with invariant culture - var values = new Dictionary + foreach (var field in UmbracoIndexFieldDefinitions) { - {"icon", new object[] {c.ContentType.Icon}}, - {PublishedFieldName, new object[] {c.Published ? 1 : 0}}, - {"id", new object[] {c.Id}}, - {"key", new object[] {c.Key}}, - {"parentID", new object[] {c.Level > 1 ? c.ParentId : -1}}, - {"level", new object[] {c.Level}}, - {"creatorID", new object[] {c.CreatorId}}, - {"sortOrder", new object[] {c.SortOrder}}, - {"createDate", new object[] {c.CreateDate}}, - {"updateDate", new object[] {c.UpdateDate}}, - {"nodeName", new object[] {c.Name}}, - {"urlName", new object[] {urlValue}}, - {"path", new object[] {c.Path}}, - {"nodeType", new object[] {c.ContentType.Id}}, - {"creatorName", new object[] {c.GetCreatorProfile(userService)?.Name ?? "??"}}, - {"writerName", new object[] {c.GetWriterProfile(userService)?.Name ?? "??"}}, - {"writerID", new object[] {c.WriterId}}, - {"template", new object[] {c.Template?.Id ?? 0}} - }; - - foreach (var property in c.Properties) - { - //only add the value if its not null or empty (we'll check for string explicitly here too) - //fixme support variants with language id - var val = property.GetValue("", ""); // for now, index the invariant values - switch (val) - { - case null: - continue; - case string strVal when strVal.IsNullOrWhiteSpace() == false: - values.Add(property.Alias, new[] { val }); - break; - default: - values.Add(property.Alias, new[] { val }); - break; - } + var def = new FieldDefinition($"{field.Name}_{lang.IsoCode.ToLowerInvariant()}", field.Type); + FieldDefinitionCollection.TryAdd(def.Name, def); } - - var vs = new ValueSet(c.Id.ToInvariantString(), IndexTypes.Content, c.ContentType.Alias, values); - - yield return vs; } + + return base.CreateFieldValueTypes(indexValueTypesFactory); } - - public static IEnumerable GetValueSets(IEnumerable urlSegmentProviders, IUserService userService, params IMedia[] media) - { - foreach (var m in media) - { - var urlValue = m.GetUrlSegment(urlSegmentProviders); - var values = new Dictionary - { - {"icon", new object[] {m.ContentType.Icon}}, - {"id", new object[] {m.Id}}, - {"key", new object[] {m.Key}}, - {"parentID", new object[] {m.Level > 1 ? m.ParentId : -1}}, - {"level", new object[] {m.Level}}, - {"creatorID", new object[] {m.CreatorId}}, - {"sortOrder", new object[] {m.SortOrder}}, - {"createDate", new object[] {m.CreateDate}}, - {"updateDate", new object[] {m.UpdateDate}}, - {"nodeName", new object[] {m.Name}}, - {"urlName", new object[] {urlValue}}, - {"path", new object[] {m.Path}}, - {"nodeType", new object[] {m.ContentType.Id}}, - {"creatorName", new object[] {m.GetCreatorProfile(userService).Name}} - }; - - foreach (var property in m.Properties) - { - //only add the value if its not null or empty (we'll check for string explicitly here too) - var val = property.GetValue(); - switch (val) - { - case null: - continue; - case string strVal when strVal.IsNullOrWhiteSpace() == false: - values.Add(property.Alias, new[] { val }); - break; - default: - values.Add(property.Alias, new[] { val }); - break; - } - } - - var vs = new ValueSet(m.Id.ToInvariantString(), IndexTypes.Media, m.ContentType.Alias, values); - - yield return vs; - } - } - - - #endregion + } } diff --git a/src/Umbraco.Examine/UmbracoContentIndexerOptions.cs b/src/Umbraco.Examine/UmbracoContentIndexerOptions.cs deleted file mode 100644 index 47b8a76c0f..0000000000 --- a/src/Umbraco.Examine/UmbracoContentIndexerOptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace Umbraco.Examine -{ - - /// - /// Options used to configure the umbraco content indexer - /// - public class UmbracoContentIndexerOptions - { - public bool SupportUnpublishedContent { get; private set; } - public bool SupportProtectedContent { get; private set; } - //TODO: We should make this a GUID! But to do that we sort of need to store the 'Path' as a comma list of GUIDs instead of int - public int? ParentId { get; private set; } - - public UmbracoContentIndexerOptions(bool supportUnpublishedContent, bool supportProtectedContent, int? parentId) - { - SupportUnpublishedContent = supportUnpublishedContent; - SupportProtectedContent = supportProtectedContent; - ParentId = parentId; - } - } -} diff --git a/src/Umbraco.Examine/UmbracoContentValueSetValidator.cs b/src/Umbraco.Examine/UmbracoContentValueSetValidator.cs deleted file mode 100644 index 01056be6b9..0000000000 --- a/src/Umbraco.Examine/UmbracoContentValueSetValidator.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Linq; -using Examine; -using Examine.LuceneEngine.Providers; -using Umbraco.Core; -using Umbraco.Core.Services; - -namespace Umbraco.Examine -{ - /// - /// Used to validate a ValueSet for content - based on permissions, parent id, etc.... - /// - public class UmbracoContentValueSetValidator : IValueSetValidator - { - private readonly UmbracoContentIndexerOptions _options; - private readonly IPublicAccessService _publicAccessService; - private const string PathKey = "path"; - public UmbracoContentValueSetValidator(UmbracoContentIndexerOptions options, IPublicAccessService publicAccessService) - { - _options = options; - _publicAccessService = publicAccessService; - } - - public bool Validate(ValueSet valueSet) - { - //check for published content - if (valueSet.Category == IndexTypes.Content - && valueSet.Values.ContainsKey(UmbracoExamineIndexer.PublishedFieldName)) - { - var published = valueSet.Values[UmbracoExamineIndexer.PublishedFieldName] != null && valueSet.Values[UmbracoExamineIndexer.PublishedFieldName][0].Equals(1); - //we don't support unpublished and the item is not published return false - if (_options.SupportUnpublishedContent == false && published == false) - { - return false; - } - } - - //must have a 'path' - if (valueSet.Values.ContainsKey(PathKey) == false) return false; - var path = valueSet.Values[PathKey]?[0].ToString() ?? string.Empty; - - // Test for access if we're only indexing published content - // return nothing if we're not supporting protected content and it is protected, and we're not supporting unpublished content - if (valueSet.Category == IndexTypes.Content - && _options.SupportUnpublishedContent == false - && _options.SupportProtectedContent == false - && _publicAccessService.IsProtected(path)) - { - return false; - } - - //check if this document is a descendent of the parent - if (_options.ParentId.HasValue && _options.ParentId.Value > 0) - { - if (path.IsNullOrWhiteSpace()) return false; - if (path.Contains(string.Concat(",", _options.ParentId.Value, ",")) == false) - return false; - } - - //check for recycle bin - if (_options.SupportUnpublishedContent == false) - { - if (path.IsNullOrWhiteSpace()) return false; - var recycleBinId = valueSet.Category == IndexTypes.Content ? Constants.System.RecycleBinContent : Constants.System.RecycleBinMedia; - if (path.Contains(string.Concat(",", recycleBinId, ","))) - return false; - } - - return true; - } - } -} diff --git a/src/Umbraco.Examine/UmbracoExamineExtensions.cs b/src/Umbraco.Examine/UmbracoExamineExtensions.cs index ab8819b276..8be5a6c1e3 100644 --- a/src/Umbraco.Examine/UmbracoExamineExtensions.cs +++ b/src/Umbraco.Examine/UmbracoExamineExtensions.cs @@ -76,17 +76,6 @@ namespace Umbraco.Examine return fieldQuery; } - /// - /// Used to replace any available tokens in the index path before the lucene directory is assigned to the path - /// - /// - internal static void ReplaceTokensInIndexPath(this IndexSet indexSet) - { - if (indexSet == null) return; - indexSet.IndexPath = indexSet.IndexPath - .Replace("{machinename}", NetworkHelper.FileSafeMachineName) - .Replace("{appdomainappid}", (HttpRuntime.AppDomainAppId ?? string.Empty).ReplaceNonAlphanumericChars("")) - .EnsureEndsWith('/'); - } + } -} \ No newline at end of file +} diff --git a/src/Umbraco.Examine/UmbracoExamineIndexDiagnostics.cs b/src/Umbraco.Examine/UmbracoExamineIndexDiagnostics.cs new file mode 100644 index 0000000000..0812d93931 --- /dev/null +++ b/src/Umbraco.Examine/UmbracoExamineIndexDiagnostics.cs @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using System.Linq; +using Lucene.Net.Store; +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; + +namespace Umbraco.Examine +{ + public class UmbracoExamineIndexDiagnostics : IIndexDiagnostics + { + private readonly UmbracoExamineIndexer _index; + private readonly ILogger _logger; + + public UmbracoExamineIndexDiagnostics(UmbracoExamineIndexer index, ILogger logger) + { + _index = index; + _logger = logger; + } + + public int DocumentCount + { + get + { + try + { + return _index.GetIndexDocumentCount(); + } + catch (AlreadyClosedException) + { + _logger.Warn(typeof(UmbracoContentIndexer), "Cannot get GetIndexDocumentCount, the writer is already closed"); + return 0; + } + } + } + + public int FieldCount + { + get + { + try + { + return _index.GetIndexFieldCount(); + } + catch (AlreadyClosedException) + { + _logger.Warn(typeof(UmbracoContentIndexer), "Cannot get GetIndexFieldCount, the writer is already closed"); + return 0; + } + } + } + + public Attempt IsHealthy() + { + var isHealthy = _index.IsHealthy(out var indexError); + return isHealthy ? Attempt.Succeed() : Attempt.Fail(indexError.Message); + } + + public virtual IReadOnlyDictionary Metadata + { + get + { + var d = new Dictionary + { + [nameof(UmbracoExamineIndexer.CommitCount)] = _index.CommitCount, + [nameof(UmbracoExamineIndexer.DefaultAnalyzer)] = _index.DefaultAnalyzer.GetType().Name, + [nameof(UmbracoExamineIndexer.DirectoryFactory)] = _index.DirectoryFactory, + [nameof(UmbracoExamineIndexer.EnableDefaultEventHandler)] = _index.EnableDefaultEventHandler, + [nameof(UmbracoExamineIndexer.LuceneIndexFolder)] = + _index.LuceneIndexFolder == null + ? string.Empty + : _index.LuceneIndexFolder.ToString().ToLowerInvariant().TrimStart(IOHelper.MapPath(SystemDirectories.Root).ToLowerInvariant()).Replace("\\", "/").EnsureStartsWith('/'), + [nameof(UmbracoExamineIndexer.PublishedValuesOnly)] = _index.PublishedValuesOnly, + //There's too much info here + //[nameof(UmbracoExamineIndexer.FieldDefinitionCollection)] = _index.FieldDefinitionCollection, + }; + + if (_index.ValueSetValidator is ValueSetValidator vsv) + { + d[nameof(ValueSetValidator.IncludeItemTypes)] = vsv.IncludeItemTypes; + d[nameof(ContentValueSetValidator.ExcludeItemTypes)] = vsv.ExcludeItemTypes; + d[nameof(ContentValueSetValidator.IncludeFields)] = vsv.IncludeFields; + d[nameof(ContentValueSetValidator.ExcludeFields)] = vsv.ExcludeFields; + } + + if (_index.ValueSetValidator is ContentValueSetValidator cvsv) + { + d[nameof(ContentValueSetValidator.PublishedValuesOnly)] = cvsv.PublishedValuesOnly; + d[nameof(ContentValueSetValidator.SupportProtectedContent)] = cvsv.SupportProtectedContent; + d[nameof(ContentValueSetValidator.ParentId)] = cvsv.ParentId; + } + + return d.Where(x => x.Value != null).ToDictionary(x => x.Key, x => x.Value); + } + } + } +} diff --git a/src/Umbraco.Examine/UmbracoExamineIndexer.cs b/src/Umbraco.Examine/UmbracoExamineIndexer.cs index a4c1fb4336..84c8a7d8c5 100644 --- a/src/Umbraco.Examine/UmbracoExamineIndexer.cs +++ b/src/Umbraco.Examine/UmbracoExamineIndexer.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.IO; using System.Linq; using Examine.LuceneEngine.Providers; using Lucene.Net.Analysis; @@ -11,19 +10,20 @@ using Umbraco.Core; using Examine; using Examine.LuceneEngine; using Examine.LuceneEngine.Indexing; +using Lucene.Net.Store; using Umbraco.Core.Composing; using Umbraco.Core.Logging; -using Umbraco.Core.Xml; using Umbraco.Examine.Config; using Directory = Lucene.Net.Store.Directory; namespace Umbraco.Examine { + /// /// An abstract provider containing the basic functionality to be able to query against /// Umbraco data. /// - public abstract class UmbracoExamineIndexer : LuceneIndexer + public abstract class UmbracoExamineIndexer : LuceneIndex, IUmbracoIndexer, IIndexDiagnostics { // note // wrapping all operations that end up calling base.SafelyProcessQueueItems in a safe call @@ -34,14 +34,15 @@ namespace Umbraco.Examine /// /// Used to store the path of a content object /// - public const string IndexPathFieldName = "__Path"; - public const string NodeKeyFieldName = "__Key"; - public const string IconFieldName = "__Icon"; - public const string PublishedFieldName = "__Published"; + public const string IndexPathFieldName = SpecialFieldPrefix + "Path"; + public const string NodeKeyFieldName = SpecialFieldPrefix + "Key"; + public const string IconFieldName = SpecialFieldPrefix + "Icon"; + public const string PublishedFieldName = SpecialFieldPrefix + "Published"; + /// /// The prefix added to a field when it is duplicated in order to store the original raw value. /// - public const string RawFieldPrefix = "__Raw_"; + public const string RawFieldPrefix = SpecialFieldPrefix + "Raw_"; /// /// Constructor for config provider based indexes @@ -52,25 +53,18 @@ namespace Umbraco.Examine { ProfilingLogger = Current.ProfilingLogger; _configBased = true; - - //This is using the config so we'll validate based on that - ValueSetValidator = new ValueSetValidatorDelegate(set => - { - - //check if this document is of a correct type of node type alias - if (ConfigIndexCriteria.IncludeItemTypes.Any()) - if (!ConfigIndexCriteria.IncludeItemTypes.Contains(set.ItemType)) - return false; - - //if this node type is part of our exclusion list, do not validate - if (ConfigIndexCriteria.ExcludeItemTypes.Any()) - if (ConfigIndexCriteria.ExcludeItemTypes.Contains(set.ItemType)) - return false; - - return true; - }); } + /// + /// Create a new + /// + /// + /// + /// + /// + /// + /// + /// protected UmbracoExamineIndexer( string name, IEnumerable fieldDefinitions, @@ -82,6 +76,12 @@ namespace Umbraco.Examine : base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, validator, indexValueTypes) { ProfilingLogger = profilingLogger ?? throw new ArgumentNullException(nameof(profilingLogger)); + + //try to set the value of `LuceneIndexFolder` for diagnostic reasons + if (luceneDirectory is FSDirectory fsDir) + LuceneIndexFolder = fsDir.Directory; + + _diagnostics = new UmbracoExamineIndexDiagnostics(this, ProfilingLogger.Logger); } private readonly bool _configBased = false; @@ -91,7 +91,7 @@ namespace Umbraco.Examine /// Alot of standard umbraco fields shouldn't be tokenized or even indexed, just stored into lucene /// for retreival after searching. /// - internal static readonly FieldDefinition[] UmbracoIndexFields = + public static readonly FieldDefinition[] UmbracoIndexFieldDefinitions = { new FieldDefinition("parentID", FieldDefinitionTypes.Integer), new FieldDefinition("level", FieldDefinitionTypes.Integer), @@ -110,6 +110,10 @@ namespace Umbraco.Examine new FieldDefinition("urlName", FieldDefinitionTypes.InvariantCultureIgnoreCase), new FieldDefinition("path", FieldDefinitionTypes.Raw), + new FieldDefinition("email", FieldDefinitionTypes.EmailAddress), + + new FieldDefinition(PublishedFieldName, FieldDefinitionTypes.Raw), + new FieldDefinition(NodeKeyFieldName, FieldDefinitionTypes.Raw), new FieldDefinition(IndexPathFieldName, FieldDefinitionTypes.Raw), new FieldDefinition(IconFieldName, FieldDefinitionTypes.Raw) }; @@ -119,17 +123,21 @@ namespace Umbraco.Examine /// /// Overridden to ensure that the umbraco system field definitions are in place /// - /// /// /// - protected override FieldValueTypeCollection CreateFieldValueTypes(Directory x, IReadOnlyDictionary> indexValueTypesFactory = null) + protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary> indexValueTypesFactory = null) { - foreach (var field in UmbracoIndexFields) + //if config based then ensure the value types else it's assumed these were passed in via ctor + if (_configBased) { - FieldDefinitionCollection.TryAdd(field.Name, field); + foreach (var field in UmbracoIndexFieldDefinitions) + { + FieldDefinitionCollection.TryAdd(field.Name, field); + } } + - return base.CreateFieldValueTypes(x, indexValueTypesFactory); + return base.CreateFieldValueTypes(indexValueTypesFactory); } /// @@ -137,10 +145,7 @@ namespace Umbraco.Examine /// public bool EnableDefaultEventHandler { get; set; } = true; - /// - /// the supported indexable types - /// - protected abstract IEnumerable SupportedTypes { get; } + public bool PublishedValuesOnly { get; protected set; } = false; protected ConfigIndexCriteria ConfigIndexCriteria { get; private set; } @@ -170,38 +175,35 @@ namespace Umbraco.Examine } //Need to check if the index set or IndexerData is specified... - if (config["indexSet"] == null && (FieldDefinitionCollection.Count == 0)) + if (config["indexSet"] == null && FieldDefinitionCollection.Count == 0) { //if we don't have either, then we'll try to set the index set by naming conventions var found = false; - if (name.EndsWith("Indexer")) + + var possibleSuffixes = new[] {"Index", "Indexer"}; + foreach (var suffix in possibleSuffixes) { - var setNameByConvension = name.Remove(name.LastIndexOf("Indexer")) + "IndexSet"; + if (!name.EndsWith(suffix)) continue; + + var setNameByConvension = name.Remove(name.LastIndexOf(suffix, StringComparison.Ordinal)) + "IndexSet"; //check if we can assign the index set by naming convention var set = IndexSets.Instance.Sets.Cast().SingleOrDefault(x => x.SetName == setNameByConvension); - if (set != null) + if (set == null) continue; + + //we've found an index set by naming conventions :) + IndexSetName = set.SetName; + + var indexSet = IndexSets.Instance.Sets[IndexSetName]; + + //get the index criteria and ensure folder + ConfigIndexCriteria = CreateFieldDefinitionsFromConfig(indexSet); + foreach (var fieldDefinition in ConfigIndexCriteria.StandardFields.Union(ConfigIndexCriteria.UserFields)) { - //we've found an index set by naming conventions :) - IndexSetName = set.SetName; - - var indexSet = IndexSets.Instance.Sets[IndexSetName]; - - //if tokens are declared in the path, then use them (i.e. {machinename} ) - indexSet.ReplaceTokensInIndexPath(); - - //get the index criteria and ensure folder - ConfigIndexCriteria = CreateFieldDefinitionsFromConfig(indexSet); - foreach (var fieldDefinition in ConfigIndexCriteria.StandardFields.Union(ConfigIndexCriteria.UserFields)) - { - FieldDefinitionCollection.TryAdd(fieldDefinition.Name, fieldDefinition); - } - - //now set the index folder - LuceneIndexFolder = new DirectoryInfo(Path.Combine(IndexSets.Instance.Sets[IndexSetName].IndexDirectory.FullName, "Index")); - - found = true; + FieldDefinitionCollection.TryAdd(fieldDefinition.Name, fieldDefinition); } + found = true; + break; } if (!found) @@ -222,86 +224,33 @@ namespace Umbraco.Examine var indexSet = IndexSets.Instance.Sets[IndexSetName]; - //if tokens are declared in the path, then use them (i.e. {machinename} ) - indexSet.ReplaceTokensInIndexPath(); - //get the index criteria and ensure folder ConfigIndexCriteria = CreateFieldDefinitionsFromConfig(indexSet); foreach (var fieldDefinition in ConfigIndexCriteria.StandardFields.Union(ConfigIndexCriteria.UserFields)) { FieldDefinitionCollection.TryAdd(fieldDefinition.Name, fieldDefinition); } - - //now set the index folder - LuceneIndexFolder = new DirectoryInfo(Path.Combine(IndexSets.Instance.Sets[IndexSetName].IndexDirectory.FullName, "Index")); } } base.Initialize(name, config); } - + #endregion - /// /// override to check if we can actually initialize. /// /// /// This check is required since the base examine lib will try to rebuild on startup /// - public override void RebuildIndex() - { - if (CanInitialize()) - { - ProfilingLogger.Logger.Debug(GetType(), "Rebuilding index"); - using (new SafeCallContext()) - { - base.RebuildIndex(); - } - } - } - - /// - /// override to check if we can actually initialize. - /// - /// - /// This check is required since the base examine lib will try to rebuild on startup - /// - public override void IndexAll(string type) + protected override void PerformDeleteFromIndex(string nodeId, Action onComplete) { if (CanInitialize()) { using (new SafeCallContext()) { - base.IndexAll(type); - } - } - } - - public override void IndexItems(IEnumerable nodes) - { - if (CanInitialize()) - { - using (new SafeCallContext()) - { - base.IndexItems(nodes); - } - } - } - - /// - /// override to check if we can actually initialize. - /// - /// - /// This check is required since the base examine lib will try to rebuild on startup - /// - public override void DeleteFromIndex(string nodeId) - { - if (CanInitialize()) - { - using (new SafeCallContext()) - { - base.DeleteFromIndex(nodeId); + base.PerformDeleteFromIndex(nodeId, onComplete); } } } @@ -317,17 +266,6 @@ namespace Umbraco.Examine return _configBased == false || Current.RuntimeState.Level == RuntimeLevel.Run; } - /// - /// Reindexes all supported types - /// - protected override void PerformIndexRebuild() - { - foreach (var t in SupportedTypes) - { - IndexAll(t); - } - } - /// /// overridden for logging /// @@ -339,17 +277,20 @@ namespace Umbraco.Examine } /// - /// This ensures that the special __Raw_ fields are indexed + /// This ensures that the special __Raw_ fields are indexed correctly /// /// protected override void OnDocumentWriting(DocumentWritingEventArgs docArgs) { var d = docArgs.Document; - foreach (var f in docArgs.ValueSet.Values.Where(x => x.Key.StartsWith(RawFieldPrefix))) + foreach (var f in docArgs.ValueSet.Values.Where(x => x.Key.StartsWith(RawFieldPrefix)).ToList()) { if (f.Value.Count > 0) { + //remove the original value so we can store it the correct way + d.RemoveField(f.Key); + d.Add(new Field( f.Key, f.Value[0].ToString(), @@ -359,26 +300,21 @@ namespace Umbraco.Examine } } - ProfilingLogger.Logger.Debug(GetType(), - "Write lucene doc id:{DocumentId}, category:{DocumentCategory}, type:{DocumentItemType}", - docArgs.ValueSet.Id, - docArgs.ValueSet.Category, - docArgs.ValueSet.ItemType); - - base.OnDocumentWriting(docArgs); } /// /// Overridden for logging. /// - protected override void AddDocument(Document doc, IndexItem item, IndexWriter writer) + protected override void AddDocument(Document doc, ValueSet valueSet, IndexWriter writer) { ProfilingLogger.Logger.Debug(GetType(), - "AddDocument {DocumentId} with type {DocumentItemType}", - item.ValueSet.Id, - item.ValueSet.ItemType); - base.AddDocument(doc, item, writer); + "Write lucene doc id:{DocumentId}, category:{DocumentCategory}, type:{DocumentItemType}", + valueSet.Id, + valueSet.Category, + valueSet.ItemType); + + base.AddDocument(doc, valueSet, writer); } protected override void OnTransformingIndexValues(IndexingItemEventArgs e) @@ -386,39 +322,16 @@ namespace Umbraco.Examine base.OnTransformingIndexValues(e); //ensure special __Path field - var path = e.IndexItem.ValueSet.GetValue("path"); + var path = e.ValueSet.GetValue("path"); if (path != null) { - e.IndexItem.ValueSet.Set(IndexPathFieldName, path); - } - - //strip html of all users fields if we detect it has HTML in it. - //if that is the case, we'll create a duplicate 'raw' copy of it so that we can return - //the value of the field 'as-is'. - foreach (var value in e.IndexItem.ValueSet.Values.ToList()) //ToList here to make a diff collection else we'll get collection modified errors - { - if (value.Value == null) continue; - - if (value.Value.Count > 0) - { - if (value.Value.First() is string str) - { - if (XmlHelper.CouldItBeXml(str)) - { - //First save the raw value to a raw field, we will change the policy of this field by detecting the prefix later - e.IndexItem.ValueSet.Values[string.Concat(RawFieldPrefix, value.Key)] = new List { str }; - //now replace the original value with the stripped html - //TODO: This should be done with an analzer?! - e.IndexItem.ValueSet.Values[value.Key] = new List { str.StripHtml() }; - } - } - } + e.ValueSet.Set(IndexPathFieldName, path); } //icon - if (e.IndexItem.ValueSet.Values.TryGetValue("icon", out var icon) && e.IndexItem.ValueSet.Values.ContainsKey(IconFieldName) == false) + if (e.ValueSet.Values.TryGetValue("icon", out var icon) && e.ValueSet.Values.ContainsKey(IconFieldName) == false) { - e.IndexItem.ValueSet.Values[IconFieldName] = icon; + e.ValueSet.Values[IconFieldName] = icon; } } @@ -431,5 +344,16 @@ namespace Umbraco.Examine indexSet.ExcludeNodeTypes.ToList().Select(x => x.Name).ToArray(), indexSet.IndexParentId); } + + #region IIndexDiagnostics + + private readonly UmbracoExamineIndexDiagnostics _diagnostics; + + public int DocumentCount => _diagnostics.DocumentCount; + public int FieldCount => _diagnostics.FieldCount; + public Attempt IsHealthy() => _diagnostics.IsHealthy(); + public virtual IReadOnlyDictionary Metadata => _diagnostics.Metadata; + + #endregion } } diff --git a/src/Umbraco.Examine/UmbracoExamineSearcher.cs b/src/Umbraco.Examine/UmbracoExamineSearcher.cs index 4b5ac50af7..50c6c21e37 100644 --- a/src/Umbraco.Examine/UmbracoExamineSearcher.cs +++ b/src/Umbraco.Examine/UmbracoExamineSearcher.cs @@ -1,156 +1,52 @@ -using System; -using System.ComponentModel; -using System.IO; -using System.Linq; -using Umbraco.Core; -using Examine.LuceneEngine.Providers; -using Lucene.Net.Analysis; -using Lucene.Net.Index; -using Umbraco.Core.Composing; -using Umbraco.Examine.Config; -using Directory = Lucene.Net.Store.Directory; +//using System; +//using System.ComponentModel; +//using System.IO; +//using System.Linq; +//using Umbraco.Core; +//using Examine.LuceneEngine.Providers; +//using Lucene.Net.Analysis; +//using Lucene.Net.Index; +//using Umbraco.Core.Composing; +//using Umbraco.Examine.Config; +//using Directory = Lucene.Net.Store.Directory; +//using Examine.LuceneEngine; +//namespace Umbraco.Examine +//{ +// /// +// /// An Examine searcher which uses Lucene.Net as the +// /// +// public class UmbracoExamineSearcher : LuceneSearcher +// { +// /// +// /// Constructor to allow for creating an indexer at runtime +// /// +// /// +// /// +// /// +// public UmbracoExamineSearcher(string name, Directory luceneDirectory, Analyzer analyzer, FieldValueTypeCollection fieldValueTypeCollection) +// : base(name, luceneDirectory, analyzer, fieldValueTypeCollection) +// { +// } -namespace Umbraco.Examine -{ - /// - /// An Examine searcher which uses Lucene.Net as the - /// - public class UmbracoExamineSearcher : LuceneSearcher - { - private readonly bool _configBased = false; +// /// +// public UmbracoExamineSearcher(string name, IndexWriter writer, Analyzer analyzer, FieldValueTypeCollection fieldValueTypeCollection) +// : base(name, writer, analyzer, fieldValueTypeCollection) +// { +// } - /// - /// Default constructor for config based construction - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public UmbracoExamineSearcher() - { - _configBased = true; - } +// /// +// /// Returns a list of fields to search on, this will also exclude the IndexPathFieldName and node type alias +// /// +// /// +// public override string[] GetAllIndexedFields() +// { +// var fields = base.GetAllIndexedFields(); +// return fields +// .Where(x => x != UmbracoExamineIndexer.IndexPathFieldName) +// .Where(x => x != LuceneIndex.ItemTypeFieldName) +// .ToArray(); +// } - /// - /// Constructor to allow for creating an indexer at runtime - /// - /// - /// - /// - public UmbracoExamineSearcher(string name, DirectoryInfo indexPath, Analyzer analyzer) - : base(name, indexPath, analyzer) - { - _configBased = false; - } - - /// - /// Constructor to allow for creating an indexer at runtime - /// - /// - /// - /// - public UmbracoExamineSearcher(string name, Directory luceneDirectory, Analyzer analyzer) - : base(name, luceneDirectory, analyzer) - { - _configBased = false; - } - - /// - public UmbracoExamineSearcher(string name, IndexWriter writer, Analyzer analyzer) : base(name, writer, analyzer) - { - _configBased = false; - } - - /// - /// Name of the Lucene.NET index set - /// - public string IndexSetName { get; private set; } - - /// - /// Method used for initializing based on a configuration based searcher - /// - /// - /// - public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) - { - if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)); - - //We need to check if we actually can initialize, if not then don't continue - if (CanInitialize() == false) - { - return; - } - - //need to check if the index set is specified, if it's not, we'll see if we can find one by convension - //if the folder is not null and the index set is null, we'll assume that this has been created at runtime. - //NOTE: Don't proceed if the _luceneDirectory is set since we already know where to look. - var luceneDirectory = GetLuceneDirectory(); - if (config["indexSet"] == null && (LuceneIndexFolder == null && luceneDirectory == null)) - { - //if we don't have either, then we'll try to set the index set by naming convensions - var found = false; - if (name.EndsWith("Searcher")) - { - var setNameByConvension = name.Remove(name.LastIndexOf("Searcher")) + "IndexSet"; - //check if we can assign the index set by naming convension - var set = IndexSets.Instance.Sets.Cast().SingleOrDefault(x => x.SetName == setNameByConvension); - - if (set != null) - { - set.ReplaceTokensInIndexPath(); - - //we've found an index set by naming convensions :) - IndexSetName = set.SetName; - found = true; - } - } - - if (!found) - throw new ArgumentNullException("indexSet on LuceneExamineIndexer provider has not been set in configuration"); - - //get the folder to index - LuceneIndexFolder = new DirectoryInfo(Path.Combine(IndexSets.Instance.Sets[IndexSetName].IndexDirectory.FullName, "Index")); - } - else if (config["indexSet"] != null && luceneDirectory == null) - { - if (IndexSets.Instance.Sets[config["indexSet"]] == null) - throw new ArgumentException("The indexSet specified for the LuceneExamineIndexer provider does not exist"); - - IndexSetName = config["indexSet"]; - - var indexSet = IndexSets.Instance.Sets[IndexSetName]; - - indexSet.ReplaceTokensInIndexPath(); - - //get the folder to index - LuceneIndexFolder = new DirectoryInfo(Path.Combine(indexSet.IndexDirectory.FullName, "Index")); - } - - base.Initialize(name, config); - - } - - /// - /// Returns true if the Umbraco application is in a state that we can initialize the examine indexes - /// - - protected bool CanInitialize() - { - // only affects indexers that are config file based, if an index was created via code then - // this has no effect, it is assumed the index would not be created if it could not be initialized - return _configBased == false || Current.RuntimeState.Level == RuntimeLevel.Run; - } - - /// - /// Returns a list of fields to search on, this will also exclude the IndexPathFieldName and node type alias - /// - /// - public override string[] GetAllIndexedFields() - { - var fields = base.GetAllIndexedFields(); - return fields - .Where(x => x != UmbracoExamineIndexer.IndexPathFieldName) - .Where(x => x != LuceneIndexer.ItemTypeFieldName) - .ToArray(); - } - - } -} +// } +//} diff --git a/src/Umbraco.Examine/UmbracoMemberIndexer.cs b/src/Umbraco.Examine/UmbracoMemberIndexer.cs index 82bf3b9cf6..4943f49825 100644 --- a/src/Umbraco.Examine/UmbracoMemberIndexer.cs +++ b/src/Umbraco.Examine/UmbracoMemberIndexer.cs @@ -5,6 +5,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Services; using System.Collections.Generic; +using System.Collections.Specialized; using System.ComponentModel; using Examine; using Examine.LuceneEngine; @@ -23,15 +24,12 @@ namespace Umbraco.Examine /// public class UmbracoMemberIndexer : UmbracoExamineIndexer { - private readonly IMemberService _memberService; - /// /// Constructor for config/provider based indexes /// [EditorBrowsable(EditorBrowsableState.Never)] public UmbracoMemberIndexer() { - _memberService = Current.Services.MemberService; } /// @@ -42,7 +40,6 @@ namespace Umbraco.Examine /// /// /// - /// /// public UmbracoMemberIndexer( string name, @@ -50,118 +47,29 @@ namespace Umbraco.Examine Directory luceneDirectory, Analyzer analyzer, ProfilingLogger profilingLogger, - IValueSetValidator validator, - IMemberService memberService) : + IValueSetValidator validator = null) : base(name, fieldDefinitions, luceneDirectory, analyzer, profilingLogger, validator) { - _memberService = memberService ?? throw new ArgumentNullException(nameof(memberService)); } + public override void Initialize(string name, NameValueCollection config) + { + base.Initialize(name, config); + + ValueSetValidator = new MemberValueSetValidator(ConfigIndexCriteria.IncludeItemTypes, ConfigIndexCriteria.ExcludeItemTypes); + } /// /// Overridden to ensure that the umbraco system field definitions are in place /// - /// /// /// - protected override FieldValueTypeCollection CreateFieldValueTypes(Directory x, IReadOnlyDictionary> indexValueTypesFactory = null) + protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary> indexValueTypesFactory = null) { var keyDef = new FieldDefinition("__key", FieldDefinitionTypes.Raw); FieldDefinitionCollection.TryAdd(keyDef.Name, keyDef); - return base.CreateFieldValueTypes(x, indexValueTypesFactory); - } - - /// - protected override IEnumerable SupportedTypes => new[] {IndexTypes.Member}; - - /// - /// Reindex all members - /// - /// - protected override void PerformIndexAll(string type) - { - //This only supports members - if (SupportedTypes.Contains(type) == false) - return; - - const int pageSize = 1000; - var pageIndex = 0; - - IMember[] members; - - if (ConfigIndexCriteria != null && ConfigIndexCriteria.IncludeItemTypes.Any()) - { - //if there are specific node types then just index those - foreach (var nodeType in ConfigIndexCriteria.IncludeItemTypes) - { - do - { - members = _memberService.GetAll(pageIndex, pageSize, out _, "LoginName", Direction.Ascending, true, null, nodeType).ToArray(); - - IndexItems(GetValueSets(members)); - - pageIndex++; - } while (members.Length == pageSize); - } - } - else - { - //no node types specified, do all members - do - { - members = _memberService.GetAll(pageIndex, pageSize, out _).ToArray(); - - IndexItems(GetValueSets(members)); - - pageIndex++; - } while (members.Length == pageSize); - } - } - - public static IEnumerable GetValueSets(params IMember[] members) - { - foreach (var m in members) - { - var values = new Dictionary - { - {"icon", new object[] {m.ContentType.Icon}}, - {"id", new object[] {m.Id}}, - {"key", new object[] {m.Key}}, - {"parentID", new object[] {m.Level > 1 ? m.ParentId : -1}}, - {"level", new object[] {m.Level}}, - {"creatorID", new object[] {m.CreatorId}}, - {"sortOrder", new object[] {m.SortOrder}}, - {"createDate", new object[] {m.CreateDate}}, - {"updateDate", new object[] {m.UpdateDate}}, - {"nodeName", new object[] {m.Name}}, - {"path", new object[] {m.Path}}, - {"nodeType", new object[] {m.ContentType.Id}}, - {"loginName", new object[] {m.Username}}, - {"email", new object[] {m.Email}}, - }; - - foreach (var property in m.Properties) - { - //only add the value if its not null or empty (we'll check for string explicitly here too) - var val = property.GetValue(); - switch (val) - { - case null: - continue; - case string strVal when strVal.IsNullOrWhiteSpace() == false: - values.Add(property.Alias, new[] { val }); - break; - default: - values.Add(property.Alias, new[] { val }); - break; - } - } - - var vs = new ValueSet(m.Id.ToInvariantString(), IndexTypes.Content, m.ContentType.Alias, values); - - yield return vs; - } + return base.CreateFieldValueTypes(indexValueTypesFactory); } /// @@ -172,21 +80,12 @@ namespace Umbraco.Examine { base.OnTransformingIndexValues(e); - if (e.IndexItem.ValueSet.Values.TryGetValue("key", out var key) && e.IndexItem.ValueSet.Values.ContainsKey("__key") == false) + if (e.ValueSet.Values.TryGetValue("key", out var key) && e.ValueSet.Values.ContainsKey("__key") == false) { //double __ prefix means it will be indexed as culture invariant - e.IndexItem.ValueSet.Values["__key"] = key; + e.ValueSet.Values["__key"] = key; } - if (e.IndexItem.ValueSet.Values.TryGetValue("email", out var email) && e.IndexItem.ValueSet.Values.ContainsKey("_searchEmail") == false) - { - if (email.Count > 0) - { - //will be indexed as full text (the default anaylyzer) - e.IndexItem.ValueSet.Values["_searchEmail"] = new List { email[0]?.ToString().Replace(".", " ").Replace("@", " ") }; - } - - } } } diff --git a/src/Umbraco.Examine/ValueSetValidator.cs b/src/Umbraco.Examine/ValueSetValidator.cs new file mode 100644 index 0000000000..4db251c0f1 --- /dev/null +++ b/src/Umbraco.Examine/ValueSetValidator.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Examine; +using Examine.LuceneEngine.Providers; +using Umbraco.Core; + +namespace Umbraco.Examine +{ + /// + /// Performing basic validation of a value set + /// + public class ValueSetValidator : IValueSetValidator + { + public ValueSetValidator( + IEnumerable includeItemTypes, + IEnumerable excludeItemTypes, + IEnumerable includeFields, + IEnumerable excludeFields) + { + IncludeItemTypes = includeItemTypes; + ExcludeItemTypes = excludeItemTypes; + IncludeFields = includeFields; + ExcludeFields = excludeFields; + ValidIndexCategories = null; + } + + protected virtual IEnumerable ValidIndexCategories { get; } + + /// + /// Optional inclusion list of content types to index + /// + /// + /// All other types will be ignored if they do not match this list + /// + public IEnumerable IncludeItemTypes { get; } + + /// + /// Optional exclusion list of content types to ignore + /// + /// + /// Any content type alias matched in this will not be included in the index + /// + public IEnumerable ExcludeItemTypes { get; } + + /// + /// Optional inclusion list of index fields to index + /// + /// + /// If specified, all other fields in a will be filtered + /// + public IEnumerable IncludeFields { get; } + + /// + /// Optional exclusion list of index fields + /// + /// + /// If specified, all fields matching these field names will be filtered from the + /// + public IEnumerable ExcludeFields { get; } + + public virtual ValueSetValidationResult Validate(ValueSet valueSet) + { + if (ValidIndexCategories != null && !ValidIndexCategories.InvariantContains(valueSet.Category)) + return ValueSetValidationResult.Failed; + + //check if this document is of a correct type of node type alias + if (IncludeItemTypes != null && !IncludeItemTypes.InvariantContains(valueSet.ItemType)) + return ValueSetValidationResult.Failed; + + //if this node type is part of our exclusion list + if (ExcludeItemTypes != null && ExcludeItemTypes.InvariantContains(valueSet.ItemType)) + return ValueSetValidationResult.Failed; + + var isFiltered = false; + + //filter based on the fields provided (if any) + if (IncludeFields != null || ExcludeFields != null) + { + foreach (var key in valueSet.Values.Keys.ToList()) + { + if (IncludeFields != null && !IncludeFields.InvariantContains(key)) + { + valueSet.Values.Remove(key); //remove any value with a key that doesn't match the inclusion list + isFiltered = true; + } + + if (ExcludeFields != null && ExcludeFields.InvariantContains(key)) + { + valueSet.Values.Remove(key); //remove any value with a key that matches the exclusion list + isFiltered = true; + } + + } + } + + return isFiltered ? ValueSetValidationResult.Filtered : ValueSetValidationResult.Valid; + } + } +} diff --git a/src/Umbraco.Tests.Benchmarks/EnumeratorBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/EnumeratorBenchmarks.cs new file mode 100644 index 0000000000..b3df1c14e8 --- /dev/null +++ b/src/Umbraco.Tests.Benchmarks/EnumeratorBenchmarks.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using BenchmarkDotNet.Attributes; + +namespace Umbraco.Tests.Benchmarks +{ + [MemoryDiagnoser] + public class EnumeratorBenchmarks + { + [Benchmark(Baseline = true)] + public void WithArray() + { + foreach (var t in EnumerateOneWithArray(1)) ; + } + + [Benchmark] + public void WithYield() + { + foreach (var t in EnumerateOneWithYield(1)) ; + } + + private IEnumerable EnumerateOneWithArray(T o) => new [] { o }; + + private IEnumerable EnumerateOneWithYield(T o) + { + yield return o; + } + } +} diff --git a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj index 6fe3655bc9..1e8c24f547 100644 --- a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj +++ b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj @@ -50,6 +50,7 @@ + diff --git a/src/Umbraco.Tests/Models/Collections/PropertyCollectionTests.cs b/src/Umbraco.Tests/Models/Collections/PropertyCollectionTests.cs index 82aae0ada5..404dc5ba74 100644 --- a/src/Umbraco.Tests/Models/Collections/PropertyCollectionTests.cs +++ b/src/Umbraco.Tests/Models/Collections/PropertyCollectionTests.cs @@ -78,7 +78,7 @@ namespace Umbraco.Tests.Models.Collections [Test] public void PropertyGroups_Collection_FirstOrDefault_Returns_Null() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); Assert.That(contentType.PropertyGroups, Is.Not.Null); Assert.That(contentType.PropertyGroups.FirstOrDefault(x => x.Name.InvariantEquals("Content")) == null, Is.False); diff --git a/src/Umbraco.Tests/Models/ContentExtensionsTests.cs b/src/Umbraco.Tests/Models/ContentExtensionsTests.cs index 38a93c0c35..5c95f1ead5 100644 --- a/src/Umbraco.Tests/Models/ContentExtensionsTests.cs +++ b/src/Umbraco.Tests/Models/ContentExtensionsTests.cs @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Models [Test] public void DirtyProperty_Reset_Clears_SavedPublishedState() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); content.PublishedState = PublishedState.Publishing; @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Models [Test] public void DirtyProperty_OnlyIfActuallyChanged_Content() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // if you assign a content property with its value it is not dirty @@ -51,7 +51,7 @@ namespace Umbraco.Tests.Models [Test] public void DirtyProperty_OnlyIfActuallyChanged_User() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); var prop = content.Properties.First(); @@ -75,7 +75,7 @@ namespace Umbraco.Tests.Models [Test] public void DirtyProperty_UpdateDate() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); var prop = content.Properties.First(); @@ -98,7 +98,7 @@ namespace Umbraco.Tests.Models [Test] public void DirtyProperty_WasDirty_ContentProperty() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); content.ResetDirtyProperties(false); Assert.IsFalse(content.IsDirty()); @@ -125,7 +125,7 @@ namespace Umbraco.Tests.Models [Test] public void DirtyProperty_WasDirty_ContentSortOrder() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); content.ResetDirtyProperties(false); Assert.IsFalse(content.IsDirty()); @@ -152,7 +152,7 @@ namespace Umbraco.Tests.Models [Test] public void DirtyProperty_WasDirty_UserProperty() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); var prop = content.Properties.First(); content.ResetDirtyProperties(false); diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 3f9c6d1cd5..d31fcbf744 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -128,7 +128,7 @@ namespace Umbraco.Tests.Models [Test] public void All_Dirty_Properties_Get_Reset() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); content.ResetDirtyProperties(false); @@ -144,7 +144,7 @@ namespace Umbraco.Tests.Models public void Can_Verify_Mocked_Content() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act @@ -157,7 +157,7 @@ namespace Umbraco.Tests.Models public void Can_Change_Property_Value() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act @@ -173,7 +173,7 @@ namespace Umbraco.Tests.Models public void Can_Set_Property_Value_As_String() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act @@ -189,7 +189,7 @@ namespace Umbraco.Tests.Models public void Can_Clone_Content_With_Reset_Identity() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); content.Id = 10; content.Key = new Guid("29181B97-CB8F-403F-86DE-5FEB497F4800"); @@ -218,7 +218,7 @@ namespace Umbraco.Tests.Models public void Can_Deep_Clone_Perf_Test() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.Id = 99; var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); var i = 200; @@ -269,7 +269,7 @@ namespace Umbraco.Tests.Models public void Can_Deep_Clone() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.Id = 99; contentType.Variations = ContentVariation.Culture; var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); @@ -394,7 +394,7 @@ namespace Umbraco.Tests.Models public void Remember_Dirty_Properties() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.Id = 99; contentType.Variations = ContentVariation.Culture; var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); @@ -475,7 +475,7 @@ namespace Umbraco.Tests.Models var ss = new SerializationService(new JsonNetSerializer()); // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.Id = 99; var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); var i = 200; @@ -530,7 +530,7 @@ namespace Umbraco.Tests.Models public void Can_Change_Property_Value_Through_Anonymous_Object() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act @@ -548,7 +548,7 @@ namespace Umbraco.Tests.Models public void Can_Verify_Dirty_Property_On_Content() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act @@ -564,7 +564,7 @@ namespace Umbraco.Tests.Models public void Can_Add_PropertyGroup_On_ContentType() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act @@ -579,7 +579,7 @@ namespace Umbraco.Tests.Models public void Can_Remove_PropertyGroup_From_ContentType() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.ResetDirtyProperties(); // Act @@ -594,7 +594,7 @@ namespace Umbraco.Tests.Models public void Can_Add_PropertyType_To_Group_On_ContentType() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act @@ -616,7 +616,7 @@ namespace Umbraco.Tests.Models public void Can_Add_New_Property_To_New_PropertyType() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act @@ -638,7 +638,7 @@ namespace Umbraco.Tests.Models public void Can_Add_New_Property_To_New_PropertyType_In_New_PropertyGroup() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act @@ -669,7 +669,7 @@ namespace Umbraco.Tests.Models public void Can_Update_PropertyType_Through_Content_Properties() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); // Act - note that the PropertyType's properties like SortOrder is not updated through the Content object @@ -689,7 +689,7 @@ namespace Umbraco.Tests.Models public void Can_Change_ContentType_On_Content() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var simpleContentType = MockedContentTypes.CreateSimpleContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); @@ -708,7 +708,7 @@ namespace Umbraco.Tests.Models public void Can_Change_ContentType_On_Content_And_Set_Property_Value() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var simpleContentType = MockedContentTypes.CreateSimpleContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); @@ -725,7 +725,7 @@ namespace Umbraco.Tests.Models public void Can_Change_ContentType_On_Content_And_Still_Get_Old_Properties() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var simpleContentType = MockedContentTypes.CreateSimpleContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); @@ -744,7 +744,7 @@ namespace Umbraco.Tests.Models public void Can_Change_ContentType_On_Content_And_Clear_Old_PropertyTypes() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var simpleContentType = MockedContentTypes.CreateSimpleContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); @@ -760,7 +760,7 @@ namespace Umbraco.Tests.Models [Test] public void Can_Verify_Content_Is_Published() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1); content.ResetDirtyProperties(); @@ -794,7 +794,7 @@ namespace Umbraco.Tests.Models public void Adding_PropertyGroup_To_ContentType_Results_In_Dirty_Entity() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.ResetDirtyProperties(); // Act @@ -811,7 +811,7 @@ namespace Umbraco.Tests.Models public void After_Committing_Changes_Was_Dirty_Is_True() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.ResetDirtyProperties(); //reset // Act @@ -828,7 +828,7 @@ namespace Umbraco.Tests.Models public void After_Committing_Changes_Was_Dirty_Is_True_On_Changed_Property() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.ResetDirtyProperties(); //reset var content = MockedContent.CreateTextpageContent(contentType, "test", -1); content.ResetDirtyProperties(); @@ -859,7 +859,7 @@ namespace Umbraco.Tests.Models public void If_Not_Committed_Was_Dirty_Is_False() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); // Act contentType.Alias = "newAlias"; @@ -873,7 +873,7 @@ namespace Umbraco.Tests.Models public void Detect_That_A_Property_Is_Removed() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); Assert.That(contentType.WasPropertyDirty("HasPropertyTypeBeenRemoved"), Is.False); // Act @@ -887,7 +887,7 @@ namespace Umbraco.Tests.Models public void Adding_PropertyType_To_PropertyGroup_On_ContentType_Results_In_Dirty_Entity() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.ResetDirtyProperties(); // Act @@ -974,7 +974,7 @@ namespace Umbraco.Tests.Models [Test] public void Can_Avoid_Circular_Dependencies_In_Composition() { - var textPage = MockedContentTypes.CreateTextpageContentType(); + var textPage = MockedContentTypes.CreateTextPageContentType(); var parent = MockedContentTypes.CreateSimpleContentType("parent", "Parent", null, true); var meta = MockedContentTypes.CreateMetaContentType(); var mixin1 = MockedContentTypes.CreateSimpleContentType("mixin1", "Mixin1", new PropertyTypeCollection(true, diff --git a/src/Umbraco.Tests/Models/ContentTypeTests.cs b/src/Umbraco.Tests/Models/ContentTypeTests.cs index a0e9a370da..6ef28d8290 100644 --- a/src/Umbraco.Tests/Models/ContentTypeTests.cs +++ b/src/Umbraco.Tests/Models/ContentTypeTests.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.Models [Test] public void Can_Deep_Clone_Content_Type_With_Reset_Identities() { - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.Id = 99; var i = 200; @@ -105,7 +105,7 @@ namespace Umbraco.Tests.Models public void Can_Deep_Clone_Content_Type_Perf_Test() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.Id = 99; var i = 200; @@ -155,7 +155,7 @@ namespace Umbraco.Tests.Models public void Can_Deep_Clone_Content_Type() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.Id = 99; var i = 200; @@ -256,7 +256,7 @@ namespace Umbraco.Tests.Models var ss = new SerializationService(new JsonNetSerializer()); // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); contentType.Id = 99; var i = 200; diff --git a/src/Umbraco.Tests/Models/ContentXmlTest.cs b/src/Umbraco.Tests/Models/ContentXmlTest.cs index 9cc41ffa6f..ab318ec1cb 100644 --- a/src/Umbraco.Tests/Models/ContentXmlTest.cs +++ b/src/Umbraco.Tests/Models/ContentXmlTest.cs @@ -18,7 +18,7 @@ namespace Umbraco.Tests.Models public void Can_Generate_Xml_Representation_Of_Content() { // Arrange - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! ServiceContext.ContentTypeService.Save(contentType); diff --git a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs index 0d5c9548fd..76e618ea26 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs @@ -427,7 +427,7 @@ namespace Umbraco.Tests.Models.Mapping // setup the mocks to return the data we want to test against... - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); MockedContentTypes.EnsureAllIds(contentType, 8888); //Act diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index 6087279285..6a282169fb 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -964,7 +964,7 @@ namespace Umbraco.Tests.Persistence.Repositories ServiceContext.ContentTypeService.Save(simpleContentType); //Create and Save ContentType "textPage" -> (NodeDto.NodeIdSeed + 1) - ContentType textpageContentType = MockedContentTypes.CreateTextpageContentType(); + ContentType textpageContentType = MockedContentTypes.CreateTextPageContentType(); ServiceContext.ContentTypeService.Save(textpageContentType); } } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index b9d106ca1b..784f534af4 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -23,6 +23,7 @@ using Umbraco.Tests.Testing; using LightInject; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; +using Umbraco.Core.PropertyEditors; namespace Umbraco.Tests.PublishedContent { @@ -112,11 +113,13 @@ namespace Umbraco.Tests.PublishedContent [Test] public void Ensure_Children_Sorted_With_Examine() { - using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, options: new UmbracoContentIndexerOptions(true, false, null))) - { + var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockMediaService()); - indexer.RebuildIndex(); + using (var luceneDir = new RandomIdRamDirectory()) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, + validator: new ContentValueSetValidator(true))) + { + rebuilder.Populate(indexer); var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); @@ -137,14 +140,15 @@ namespace Umbraco.Tests.PublishedContent [Test] public void Do_Not_Find_In_Recycle_Bin() { + var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockMediaService()); + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, //include unpublished content since this uses the 'internal' indexer, it's up to the media cache to filter - options: new UmbracoContentIndexerOptions(true, false, null))) + validator: new ContentValueSetValidator(true))) using (indexer.ProcessNonAsync()) { - indexer.RebuildIndex(); - + rebuilder.Populate(indexer); var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); @@ -183,12 +187,14 @@ namespace Umbraco.Tests.PublishedContent [Test] public void Children_With_Examine() { + var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockMediaService()); + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, options: new UmbracoContentIndexerOptions(true, false, null))) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, + validator: new ContentValueSetValidator(true))) using (indexer.ProcessNonAsync()) { - indexer.RebuildIndex(); - + rebuilder.Populate(indexer); var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); @@ -208,12 +214,14 @@ namespace Umbraco.Tests.PublishedContent [Test] public void Descendants_With_Examine() { + var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockMediaService()); + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, options: new UmbracoContentIndexerOptions(true, false, null))) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, + validator: new ContentValueSetValidator(true))) using (indexer.ProcessNonAsync()) { - indexer.RebuildIndex(); - + rebuilder.Populate(indexer); var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); @@ -233,12 +241,14 @@ namespace Umbraco.Tests.PublishedContent [Test] public void DescendantsOrSelf_With_Examine() { + var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockMediaService()); + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, options: new UmbracoContentIndexerOptions(true, false, null))) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, + validator: new ContentValueSetValidator(true))) using (indexer.ProcessNonAsync()) { - indexer.RebuildIndex(); - + rebuilder.Populate(indexer); var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); @@ -258,12 +268,15 @@ namespace Umbraco.Tests.PublishedContent [Test] public void Ancestors_With_Examine() { + var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockMediaService()); + + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, options: new UmbracoContentIndexerOptions(true, false, null))) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, + validator: new ContentValueSetValidator(true))) using (indexer.ProcessNonAsync()) { - indexer.RebuildIndex(); - + rebuilder.Populate(indexer); var ctx = GetUmbracoContext("/test"); var searcher = indexer.GetSearcher(); @@ -280,11 +293,14 @@ namespace Umbraco.Tests.PublishedContent [Test] public void AncestorsOrSelf_With_Examine() { + var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockMediaService()); + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, options: new UmbracoContentIndexerOptions(true, false, null))) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, + validator: new ContentValueSetValidator(true))) using (indexer.ProcessNonAsync()) { - indexer.RebuildIndex(); + rebuilder.Populate(indexer); var ctx = GetUmbracoContext("/test"); diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index 4d4825323c..322b79429e 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -65,9 +65,9 @@ namespace Umbraco.Tests.Services // ... NOPE, made even more nice changes, it is now... // 4452ms !!!!!!! - var contentType1 = MockedContentTypes.CreateTextpageContentType("test1", "test1"); - var contentType2 = MockedContentTypes.CreateTextpageContentType("test2", "test2"); - var contentType3 = MockedContentTypes.CreateTextpageContentType("test3", "test3"); + var contentType1 = MockedContentTypes.CreateTextPageContentType("test1", "test1"); + var contentType2 = MockedContentTypes.CreateTextPageContentType("test2", "test2"); + var contentType3 = MockedContentTypes.CreateTextPageContentType("test3", "test3"); ServiceContext.ContentTypeService.Save(new[] { contentType1, contentType2, contentType3 }); contentType1.AllowedContentTypes = new[] { @@ -291,7 +291,7 @@ namespace Umbraco.Tests.Services public void CreateTestData() { //Create and Save ContentType "textpage" -> NodeDto.NodeIdSeed - ContentType contentType = MockedContentTypes.CreateTextpageContentType(); + ContentType contentType = MockedContentTypes.CreateTextPageContentType(); ServiceContext.ContentTypeService.Save(contentType); } } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 494d12dbe1..d3ebf703a5 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -92,7 +92,7 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; var contentTypeService = ServiceContext.ContentTypeService; - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); contentTypeService.Save(contentType); @@ -118,7 +118,7 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; var contentTypeService = ServiceContext.ContentTypeService; - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); contentTypeService.Save(contentType); @@ -142,7 +142,7 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; var contentTypeService = ServiceContext.ContentTypeService; - var contentType = MockedContentTypes.CreateTextpageContentType(); + var contentType = MockedContentTypes.CreateTextPageContentType(); ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); contentTypeService.Save(contentType); @@ -170,10 +170,10 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; var contentTypeService = ServiceContext.ContentTypeService; - var ct1 = MockedContentTypes.CreateTextpageContentType("ct1"); + var ct1 = MockedContentTypes.CreateTextPageContentType("ct1"); ServiceContext.FileService.SaveTemplate(ct1.DefaultTemplate); contentTypeService.Save(ct1); - var ct2 = MockedContentTypes.CreateTextpageContentType("ct2"); + var ct2 = MockedContentTypes.CreateTextPageContentType("ct2"); ServiceContext.FileService.SaveTemplate(ct2.DefaultTemplate); contentTypeService.Save(ct2); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs index f186ae8e83..bc0854bdb7 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs @@ -611,7 +611,7 @@ namespace Umbraco.Tests.Services [Test] public void Deleting_PropertyType_Removes_The_Property_From_Content() { - IContentType contentType1 = MockedContentTypes.CreateTextpageContentType("test1", "Test1"); + IContentType contentType1 = MockedContentTypes.CreateTextPageContentType("test1", "Test1"); ServiceContext.FileService.SaveTemplate(contentType1.DefaultTemplate); ServiceContext.ContentTypeService.Save(contentType1); IContent contentItem = MockedContent.CreateTextpageContent(contentType1, "Testing", -1); @@ -633,11 +633,11 @@ namespace Umbraco.Tests.Services [Test] public void Rebuild_Content_Xml_On_Alias_Change() { - var contentType1 = MockedContentTypes.CreateTextpageContentType("test1", "Test1"); + var contentType1 = MockedContentTypes.CreateTextPageContentType("test1", "Test1"); ServiceContext.FileService.SaveTemplate(contentType1.DefaultTemplate); ServiceContext.ContentTypeService.Save(contentType1); - var contentType2 = MockedContentTypes.CreateTextpageContentType("test2", "Test2"); + var contentType2 = MockedContentTypes.CreateTextPageContentType("test2", "Test2"); ServiceContext.FileService.SaveTemplate(contentType2.DefaultTemplate); ServiceContext.ContentTypeService.Save(contentType2); @@ -701,7 +701,7 @@ namespace Umbraco.Tests.Services [Test] public void Rebuild_Content_Xml_On_Property_Removal() { - var contentType1 = MockedContentTypes.CreateTextpageContentType("test1", "Test1"); + var contentType1 = MockedContentTypes.CreateTextPageContentType("test1", "Test1"); ServiceContext.FileService.SaveTemplate(contentType1.DefaultTemplate); ServiceContext.ContentTypeService.Save(contentType1); var contentItems1 = MockedContent.CreateTextpageContent(contentType1, -1, 10).ToArray(); diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index fe0e46941a..c65faf76c9 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -169,12 +169,10 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting Mock.Of(), mockedTypedContent, Mock.Of(), - Mock.Of(), Mock.Of(), Mock.Of(), membershipHelper, - serviceContext, - CacheHelper.NoCache); + serviceContext); return CreateController(controllerType, request, umbHelper); } diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs index 42beea7df3..14b967b1c9 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs +++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.TestHelpers.Entities return contentType; } - public static ContentType CreateTextpageContentType(string alias = "textPage", string name = "Text Page") + public static ContentType CreateTextPageContentType(string alias = "textPage", string name = "Text Page") { var contentType = new ContentType(-1) { diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs b/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs index 14c6a08c8b..f8d48c5703 100644 --- a/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs +++ b/src/Umbraco.Tests/TestHelpers/Stubs/TestExamineManager.cs @@ -6,64 +6,38 @@ namespace Umbraco.Tests.TestHelpers.Stubs { internal class TestExamineManager : IExamineManager { - private readonly ConcurrentDictionary _indexers = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _indexers = new ConcurrentDictionary(); private readonly ConcurrentDictionary _searchers = new ConcurrentDictionary(); - public void AddIndexer(string name, IIndexer indexer) + public void AddIndex(IIndex indexer) { - _indexers.TryAdd(name, indexer); + _indexers.TryAdd(indexer.Name, indexer); } - public void AddSearcher(string name, ISearcher searcher) + public void AddSearcher(ISearcher searcher) { - _searchers.TryAdd(name, searcher); + _searchers.TryAdd(searcher.Name, searcher); } - - public void DeleteFromIndexes(string nodeId) - { - //noop - } - - public void DeleteFromIndexes(string nodeId, IEnumerable providers) - { - //noop - } - + public void Dispose() { //noop } - public IIndexer GetIndexer(string indexerName) + public bool TryGetIndex(string indexName, out IIndex index) { - return _indexers.TryGetValue(indexerName, out var indexer) ? indexer : null; + return _indexers.TryGetValue(indexName, out index); } - public ISearcher GetRegisteredSearcher(string searcherName) + public bool TryGetSearcher(string searcherName, out ISearcher searcher) { - return _searchers.TryGetValue(searcherName, out var indexer) ? indexer : null; + return _searchers.TryGetValue(searcherName, out searcher); } - public void IndexAll(string indexCategory) - { - //noop - } + public IEnumerable Indexes => _indexers.Values; - public void IndexItems(ValueSet[] nodes) - { - //noop - } + public IEnumerable RegisteredSearchers => _searchers.Values; - public void IndexItems(ValueSet[] nodes, IEnumerable providers) - { - //noop - } - - public void RebuildIndexes() - { - //noop - } - - public IReadOnlyDictionary IndexProviders => _indexers; + public IReadOnlyDictionary IndexProviders => _indexers; } } diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index e79e504a69..d5f5778d1a 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -62,12 +62,10 @@ namespace Umbraco.Tests.Testing.TestingTests Mock.Of(), Mock.Of(), Mock.Of(), - Mock.Of(), Mock.Of(), Mock.Of(), new MembershipHelper(umbracoContext, Mock.Of(), Mock.Of()), - new ServiceContext(), - CacheHelper.CreateDisabledCacheHelper()); + new ServiceContext()); Assert.Pass(); } diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index e901f3689e..08976670f4 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -77,7 +77,7 @@ - + 1.8.9 @@ -207,6 +207,7 @@ + @@ -464,7 +465,6 @@ - True True diff --git a/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs b/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs index e2279ee833..47fa32cbaa 100644 --- a/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs @@ -1,13 +1,16 @@ using System; using System.Linq; using Examine; +using LightInject; using Lucene.Net.Store; using NUnit.Framework; using Umbraco.Tests.Testing; using Umbraco.Examine; +using Umbraco.Core.PropertyEditors; namespace Umbraco.Tests.UmbracoExamine { + [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class EventsTest : ExamineBaseTest @@ -16,13 +19,13 @@ namespace Umbraco.Tests.UmbracoExamine public void Events_Ignoring_Node() { using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, //make parent id 999 so all are ignored - options: new UmbracoContentIndexerOptions(false, false, 999))) + validator: new ContentValueSetValidator(false, 999))) using (indexer.ProcessNonAsync()) { var searcher = indexer.GetSearcher(); - + var contentService = new ExamineDemoDataContentService(); //get a node from the data repo var node = contentService.GetPublishedContentByXPath("//*[string-length(@id)>0 and number(@id)>0]") @@ -31,9 +34,9 @@ namespace Umbraco.Tests.UmbracoExamine .First(); var valueSet = node.ConvertToValueSet(IndexTypes.Content); - indexer.IndexItems(new[] {valueSet}); + indexer.IndexItems(new[] { valueSet }); - var found = searcher.Search(searcher.CreateCriteria().Id((string) node.Attribute("id")).Compile()); + var found = searcher.Search(searcher.CreateCriteria().Id((string)node.Attribute("id")).Compile()); Assert.AreEqual(0, found.TotalItemCount); } diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs index 8b57e10849..1f849fc1ce 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -28,177 +29,158 @@ namespace Umbraco.Tests.UmbracoExamine /// internal static class IndexInitializer { + public static ContentValueSetBuilder GetContentValueSetBuilder(PropertyEditorCollection propertyEditors, bool publishedValuesOnly) + { + var contentValueSetBuilder = new ContentValueSetBuilder(propertyEditors, new[] { new DefaultUrlSegmentProvider() }, GetMockUserService(), publishedValuesOnly); + return contentValueSetBuilder; + } + + public static ContentIndexPopulator GetContentIndexRebuilder(PropertyEditorCollection propertyEditors, IContentService contentService, ISqlContext sqlContext, bool publishedValuesOnly) + { + var contentValueSetBuilder = GetContentValueSetBuilder(propertyEditors, publishedValuesOnly); + var contentIndexDataSource = new ContentIndexPopulator(true, null, contentService, sqlContext, contentValueSetBuilder); + return contentIndexDataSource; + } + + public static MediaIndexPopulator GetMediaIndexRebuilder(PropertyEditorCollection propertyEditors, IMediaService mediaService) + { + var mediaValueSetBuilder = new MediaValueSetBuilder(propertyEditors, new[] { new DefaultUrlSegmentProvider() }, GetMockUserService()); + var mediaIndexDataSource = new MediaIndexPopulator(null, mediaService, mediaValueSetBuilder); + return mediaIndexDataSource; + } + + public static IContentService GetMockContentService() + { + long longTotalRecs; + var demoData = new ExamineDemoDataContentService(); + + var allRecs = demoData.GetLatestContentByXPath("//*[@isDoc]") + .Root + .Elements() + .Select(x => Mock.Of( + m => + m.Id == (int)x.Attribute("id") && + m.ParentId == (int)x.Attribute("parentID") && + m.Level == (int)x.Attribute("level") && + m.CreatorId == 0 && + m.SortOrder == (int)x.Attribute("sortOrder") && + m.CreateDate == (DateTime)x.Attribute("createDate") && + m.UpdateDate == (DateTime)x.Attribute("updateDate") && + m.Name == (string)x.Attribute("nodeName") && + m.GetCultureName(It.IsAny()) == (string)x.Attribute("nodeName") && + m.Path == (string)x.Attribute("path") && + m.Properties == new PropertyCollection() && + m.ContentType == Mock.Of(mt => + mt.Icon == "test" && + mt.Alias == x.Name.LocalName && + mt.Id == (int)x.Attribute("nodeType")))) + .ToArray(); + + + return Mock.Of( + x => x.GetPagedDescendants( + It.IsAny(), It.IsAny(), It.IsAny(), out longTotalRecs, It.IsAny>(), It.IsAny()) + == allRecs); + } + + public static IUserService GetMockUserService() + { + return Mock.Of(x => x.GetProfileById(It.IsAny()) == Mock.Of(p => p.Id == 0 && p.Name == "admin")); + } + + public static IMediaService GetMockMediaService() + { + long totalRecs; + + var demoData = new ExamineDemoDataMediaService(); + + var allRecs = demoData.GetLatestMediaByXpath("//node") + .Root + .Elements() + .Select(x => Mock.Of( + m => + m.Id == (int)x.Attribute("id") && + m.ParentId == (int)x.Attribute("parentID") && + m.Level == (int)x.Attribute("level") && + m.CreatorId == 0 && + m.SortOrder == (int)x.Attribute("sortOrder") && + m.CreateDate == (DateTime)x.Attribute("createDate") && + m.UpdateDate == (DateTime)x.Attribute("updateDate") && + m.Name == (string)x.Attribute("nodeName") && + m.GetCultureName(It.IsAny()) == (string)x.Attribute("nodeName") && + m.Path == (string)x.Attribute("path") && + m.Properties == new PropertyCollection() && + m.ContentType == Mock.Of(mt => + mt.Alias == (string)x.Attribute("nodeTypeAlias") && + mt.Id == (int)x.Attribute("nodeType")))) + .ToArray(); + + // MOCK! + var mediaServiceMock = new Mock(); + + mediaServiceMock + .Setup(x => x.GetPagedDescendants( + It.IsAny(), It.IsAny(), It.IsAny(), out totalRecs, It.IsAny>(), It.IsAny()) + ).Returns(() => allRecs); + + //mediaServiceMock.Setup(service => service.GetPagedXmlEntries(It.IsAny(), It.IsAny(), It.IsAny(), out longTotalRecs)) + // .Returns(() => allRecs.Select(x => x.ToXml())); + + return mediaServiceMock.Object; + } + + public static ILocalizationService GetMockLocalizationService() + { + return Mock.Of(x => x.GetAllLanguages() == Array.Empty()); + } + + public static IMediaTypeService GetMockMediaTypeService() + { + var mediaTypeServiceMock = new Mock(); + mediaTypeServiceMock.Setup(x => x.GetAll()) + .Returns(new List + { + new MediaType(-1) {Alias = "Folder", Name = "Folder", Id = 1031, Icon = "icon-folder"}, + new MediaType(-1) {Alias = "Image", Name = "Image", Id = 1032, Icon = "icon-picture"} + }); + return mediaTypeServiceMock.Object; + } + public static UmbracoContentIndexer GetUmbracoIndexer( ProfilingLogger profilingLogger, Directory luceneDir, - ISqlContext sqlContext, Analyzer analyzer = null, - IContentService contentService = null, - IMediaService mediaService = null, - IMemberService memberService = null, - IUserService userService = null, - IContentTypeService contentTypeService = null, - IMediaTypeService mediaTypeService = null, - UmbracoContentIndexerOptions options = null) + ILocalizationService languageService = null, + IContentValueSetValidator validator = null) { - if (contentService == null) - { - long longTotalRecs; - var demoData = new ExamineDemoDataContentService(); - - var allRecs = demoData.GetLatestContentByXPath("//*[@isDoc]") - .Root - .Elements() - .Select(x => Mock.Of( - m => - m.Id == (int)x.Attribute("id") && - m.ParentId == (int)x.Attribute("parentID") && - m.Level == (int)x.Attribute("level") && - m.CreatorId == 0 && - m.SortOrder == (int)x.Attribute("sortOrder") && - m.CreateDate == (DateTime)x.Attribute("createDate") && - m.UpdateDate == (DateTime)x.Attribute("updateDate") && - m.Name == (string)x.Attribute("nodeName") && - m.GetCultureName(It.IsAny()) == (string)x.Attribute("nodeName") && - m.Path == (string)x.Attribute("path") && - m.Properties == new PropertyCollection() && - m.ContentType == Mock.Of(mt => - mt.Icon == "test" && - mt.Alias == x.Name.LocalName && - mt.Id == (int)x.Attribute("nodeType")))) - .ToArray(); - - - contentService = Mock.Of( - x => x.GetPagedDescendants( - It.IsAny(), It.IsAny(), It.IsAny(), out longTotalRecs, It.IsAny>(), It.IsAny()) - == - allRecs); - } - if (userService == null) - { - userService = Mock.Of(x => x.GetProfileById(It.IsAny()) == Mock.Of(p => p.Id == 0 && p.Name == "admin")); - } - - if (mediaService == null) - { - long totalRecs; - - var demoData = new ExamineDemoDataMediaService(); - - var allRecs = demoData.GetLatestMediaByXpath("//node") - .Root - .Elements() - .Select(x => Mock.Of( - m => - m.Id == (int) x.Attribute("id") && - m.ParentId == (int) x.Attribute("parentID") && - m.Level == (int) x.Attribute("level") && - m.CreatorId == 0 && - m.SortOrder == (int) x.Attribute("sortOrder") && - m.CreateDate == (DateTime) x.Attribute("createDate") && - m.UpdateDate == (DateTime) x.Attribute("updateDate") && - m.Name == (string) x.Attribute("nodeName") && - m.GetCultureName(It.IsAny()) == (string)x.Attribute("nodeName") && - m.Path == (string) x.Attribute("path") && - m.Properties == new PropertyCollection() && - m.ContentType == Mock.Of(mt => - mt.Alias == (string) x.Attribute("nodeTypeAlias") && - mt.Id == (int) x.Attribute("nodeType")))) - .ToArray(); - - // MOCK! - var mediaServiceMock = new Mock(); - - mediaServiceMock - .Setup(x => x.GetPagedDescendants( - It.IsAny(), It.IsAny(), It.IsAny(), out totalRecs, It.IsAny>(), It.IsAny()) - ).Returns(() => allRecs); - - //mediaServiceMock.Setup(service => service.GetPagedXmlEntries(It.IsAny(), It.IsAny(), It.IsAny(), out longTotalRecs)) - // .Returns(() => allRecs.Select(x => x.ToXml())); - - mediaService = mediaServiceMock.Object; - - } + if (languageService == null) + languageService = GetMockLocalizationService(); if (analyzer == null) - { analyzer = new StandardAnalyzer(Version.LUCENE_30); - } - //var indexSet = new IndexSet(); - // var indexCriteria = indexSet.ToIndexCriteria(dataService, UmbracoContentIndexer.IndexFieldPolicies); - - //var i = new UmbracoContentIndexer(indexCriteria, - // luceneDir, //custom lucene directory - // dataService, - // contentService, - // mediaService, - // dataTypeService, - // userService, - // new[] { new DefaultUrlSegmentProvider() }, - // analyzer, - // false); - - //i.IndexSecondsInterval = 1; - - if (options == null) - { - options = new UmbracoContentIndexerOptions(false, false, null); - } - - if (mediaTypeService == null) - { - var mediaTypeServiceMock = new Mock(); - mediaTypeServiceMock.Setup(x => x.GetAll()) - .Returns(new List - { - new MediaType(-1) {Alias = "Folder", Name = "Folder", Id = 1031, Icon = "icon-folder"}, - new MediaType(-1) {Alias = "Image", Name = "Image", Id = 1032, Icon = "icon-picture"} - }); - mediaTypeService = mediaTypeServiceMock.Object; - } - - // fixme oops?! - //var query = new Mock>(); - //query - // .Setup(x => x.GetWhereClauses()) - // .Returns(new List> { new Tuple($"{Constants.DatabaseSchema.Tables.Document}.published", new object[] { 1 }) }); + if (validator == null) + validator = new ContentValueSetValidator(true); - //scopeProvider - // .Setup(x => x.Query()) - // .Returns(query.Object); - var i = new UmbracoContentIndexer( "testIndexer", - Enumerable.Empty(), + UmbracoExamineIndexer.UmbracoIndexFieldDefinitions, luceneDir, analyzer, profilingLogger, - contentService, - mediaService, - userService, - sqlContext, - new[] {new DefaultUrlSegmentProvider()}, - new UmbracoContentValueSetValidator(options, Mock.Of()), - options); + languageService, + validator); i.IndexingError += IndexingError; return i; } - public static LuceneSearcher GetLuceneSearcher(Directory luceneDir) - { - return new LuceneSearcher("testSearcher", luceneDir, new StandardAnalyzer(Version.LUCENE_29)); - } - - public static MultiIndexSearcher GetMultiSearcher(Directory pdfDir, Directory simpleDir, Directory conventionDir, Directory cwsDir) - { - var i = new MultiIndexSearcher("testSearcher", new[] { pdfDir, simpleDir, conventionDir, cwsDir }, new StandardAnalyzer(Version.LUCENE_29)); - return i; - } + //public static MultiIndexSearcher GetMultiSearcher(Directory pdfDir, Directory simpleDir, Directory conventionDir, Directory cwsDir) + //{ + // var i = new MultiIndexSearcher("testSearcher", new[] { pdfDir, simpleDir, conventionDir, cwsDir }, new StandardAnalyzer(Version.LUCENE_29)); + // return i; + //} internal static void IndexingError(object sender, IndexingErrorEventArgs e) diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs b/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs index db6f174f59..78bdb37cae 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs @@ -8,6 +8,13 @@ using Lucene.Net.Store; using NUnit.Framework; using Umbraco.Tests.Testing; using Umbraco.Examine; +using Umbraco.Core.PropertyEditors; +using LightInject; +using Umbraco.Tests.TestHelpers.Entities; +using Umbraco.Core.Models; +using Newtonsoft.Json; +using System.Collections.Generic; +using System; namespace Umbraco.Tests.UmbracoExamine { @@ -21,16 +28,116 @@ namespace Umbraco.Tests.UmbracoExamine { [Test] - public void Rebuild_Index() + public void Index_Property_Data_With_Value_Indexer() { + var contentValueSetBuilder = IndexInitializer.GetContentValueSetBuilder(Container.GetInstance(), false); + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, options: new UmbracoContentIndexerOptions(true, false, null))) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, + validator: new ContentValueSetValidator(false))) using (indexer.ProcessNonAsync()) { + indexer.CreateIndex(); + + var contentType = MockedContentTypes.CreateBasicContentType(); + contentType.AddPropertyType(new PropertyType("test", ValueStorageType.Ntext) + { + Alias = "grid", + Name = "Grid", + PropertyEditorAlias = Core.Constants.PropertyEditors.Aliases.Grid + }); + var content = MockedContent.CreateBasicContent(contentType); + content.Id = 555; + content.Path = "-1,555"; + var gridVal = new GridValue + { + Name = "n1", + Sections = new List + { + new GridValue.GridSection + { + Grid = "g1", + Rows = new List + { + new GridValue.GridRow + { + Id = Guid.NewGuid(), + Name = "row1", + Areas = new List + { + new GridValue.GridArea + { + Grid = "g2", + Controls = new List + { + new GridValue.GridControl + { + Editor = new GridValue.GridEditor + { + Alias = "editor1", + View = "view1" + }, + Value = "value1" + }, + new GridValue.GridControl + { + Editor = new GridValue.GridEditor + { + Alias = "editor1", + View = "view1" + }, + Value = "value2" + } + } + } + } + } + } + } + } + }; + + var json = JsonConvert.SerializeObject(gridVal); + content.Properties["grid"].SetValue(json); + + var valueSet = contentValueSetBuilder.GetValueSets(content); + indexer.IndexItems(valueSet); + + var searcher = indexer.GetSearcher(); + + var results = searcher.Search(searcher.CreateCriteria().Id(555).Compile()); + Assert.AreEqual(1, results.TotalItemCount); + + var result = results.First(); + Assert.IsTrue(result.Values.ContainsKey("grid.row1")); + Assert.AreEqual("value1", result.AllValues["grid.row1"][0]); + Assert.AreEqual("value2", result.AllValues["grid.row1"][1]); + Assert.IsTrue(result.Values.ContainsKey("grid")); + Assert.AreEqual("value1 value2 ", result["grid"]); + Assert.IsTrue(result.Values.ContainsKey($"{UmbracoExamineIndexer.RawFieldPrefix}grid")); + Assert.AreEqual(json, result[$"{UmbracoExamineIndexer.RawFieldPrefix}grid"]); + } + } + + [Test] + public void Rebuild_Index() + { + var contentRebuilder = IndexInitializer.GetContentIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockContentService(), ScopeProvider.SqlContext, false); + var mediaRebuilder = IndexInitializer.GetMediaIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockMediaService()); + + using (var luceneDir = new RandomIdRamDirectory()) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, + validator: new ContentValueSetValidator(false))) + using (indexer.ProcessNonAsync()) + { + contentRebuilder.RegisterIndex(indexer.Name); + mediaRebuilder.RegisterIndex(indexer.Name); + var searcher = indexer.GetSearcher(); //create the whole thing - indexer.RebuildIndex(); + contentRebuilder.Populate(indexer); + mediaRebuilder.Populate(indexer); var result = searcher.Search(searcher.CreateCriteria().All().Compile()); @@ -45,23 +152,27 @@ namespace Umbraco.Tests.UmbracoExamine [Test] public void Index_Protected_Content_Not_Indexed() { + var rebuilder = IndexInitializer.GetContentIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockContentService(), ScopeProvider.SqlContext, false); + + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext)) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir)) using (indexer.ProcessNonAsync()) using (var searcher = ((LuceneSearcher)indexer.GetSearcher()).GetLuceneSearcher()) { //create the whole thing - indexer.RebuildIndex(); + rebuilder.Populate(indexer); + var protectedQuery = new BooleanQuery(); protectedQuery.Add( new BooleanClause( - new TermQuery(new Term(LuceneIndexer.CategoryFieldName, IndexTypes.Content)), + new TermQuery(new Term(LuceneIndex.CategoryFieldName, IndexTypes.Content)), Occur.MUST)); protectedQuery.Add( new BooleanClause( - new TermQuery(new Term(LuceneIndexer.ItemIdFieldName, ExamineDemoDataContentService.ProtectedNode.ToString())), + new TermQuery(new Term(LuceneIndex.ItemIdFieldName, ExamineDemoDataContentService.ProtectedNode.ToString())), Occur.MUST)); var collector = TopScoreDocCollector.Create(100, true); @@ -76,10 +187,11 @@ namespace Umbraco.Tests.UmbracoExamine [Test] public void Index_Move_Media_From_Non_Indexable_To_Indexable_ParentID() { + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, //make parent id 1116 - options: new UmbracoContentIndexerOptions(false, false, 1116))) + validator: new ContentValueSetValidator(false, 1116))) using (indexer.ProcessNonAsync()) { var searcher = indexer.GetSearcher(); @@ -95,7 +207,7 @@ namespace Umbraco.Tests.UmbracoExamine Assert.AreEqual("-1,1111,2222,2112", currPath); //ensure it's indexed - indexer.IndexItems(new []{ node.ConvertToValueSet(IndexTypes.Media) }); + indexer.IndexItem(node.ConvertToValueSet(IndexTypes.Media)); //it will not exist because it exists under 2222 var results = searcher.Search(searcher.CreateCriteria().Id(2112).Compile()); @@ -119,9 +231,9 @@ namespace Umbraco.Tests.UmbracoExamine public void Index_Move_Media_To_Non_Indexable_ParentID() { using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer1 = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, + using (var indexer1 = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, //make parent id 2222 - options: new UmbracoContentIndexerOptions(false, false, 2222))) + validator: new ContentValueSetValidator(false, 2222))) using (indexer1.ProcessNonAsync()) { var searcher = indexer1.GetSearcher(); @@ -137,7 +249,7 @@ namespace Umbraco.Tests.UmbracoExamine Assert.AreEqual("-1,1111,2222,2112", currPath); //ensure it's indexed - indexer1.IndexItems(new[] { node.ConvertToValueSet(IndexTypes.Media) }); + indexer1.IndexItem(node.ConvertToValueSet(IndexTypes.Media)); @@ -168,17 +280,20 @@ namespace Umbraco.Tests.UmbracoExamine [Test] public void Index_Reindex_Content() { + var rebuilder = IndexInitializer.GetContentIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockContentService(), ScopeProvider.SqlContext, false); using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, options: new UmbracoContentIndexerOptions(true, false, null))) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, + validator: new ContentValueSetValidator(false))) using (indexer.ProcessNonAsync()) { + rebuilder.RegisterIndex(indexer.Name); + var searcher = indexer.GetSearcher(); //create the whole thing - indexer.RebuildIndex(); + rebuilder.Populate(indexer); - - var result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndexer.CategoryFieldName, IndexTypes.Content).Compile()); + var result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Compile()); Assert.AreEqual(21, result.TotalItemCount); //delete all content @@ -189,15 +304,13 @@ namespace Umbraco.Tests.UmbracoExamine //ensure it's all gone - result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndexer.CategoryFieldName, IndexTypes.Content).Compile()); + result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Compile()); Assert.AreEqual(0, result.TotalItemCount); //call our indexing methods - indexer.IndexAll(IndexTypes.Content); + rebuilder.Populate(indexer); - - - result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndexer.CategoryFieldName, IndexTypes.Content).Compile()); + result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Compile()); Assert.AreEqual(21, result.TotalItemCount); } } @@ -208,15 +321,17 @@ namespace Umbraco.Tests.UmbracoExamine [Test] public void Index_Delete_Index_Item_Ensure_Heirarchy_Removed() { + + var rebuilder = IndexInitializer.GetContentIndexRebuilder(Container.GetInstance(), IndexInitializer.GetMockContentService(), ScopeProvider.SqlContext, false); + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext)) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir)) using (indexer.ProcessNonAsync()) { var searcher = indexer.GetSearcher(); //create the whole thing - indexer.RebuildIndex(); - + rebuilder.Populate(indexer); //now delete a node that has children diff --git a/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs b/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs index 768d1c735c..a01d49cc22 100644 --- a/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs +++ b/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs @@ -1,17 +1,19 @@ using System; using System.Collections.Generic; using System.Linq; +using LightInject; using Examine; -using Lucene.Net.Store; using NUnit.Framework; using Examine.LuceneEngine.SearchCriteria; using Moq; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Services; using Umbraco.Examine; using Umbraco.Tests.Testing; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Strings; namespace Umbraco.Tests.UmbracoExamine { @@ -53,13 +55,17 @@ namespace Umbraco.Tests.UmbracoExamine == allRecs); + var propertyEditors = Container.GetInstance(); + var rebuilder = IndexInitializer.GetContentIndexRebuilder(propertyEditors, contentService, ScopeProvider.SqlContext, true); + using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, ScopeProvider.SqlContext, contentService: contentService)) + using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir)) using (indexer.ProcessNonAsync()) { - indexer.RebuildIndex(); + rebuilder.RegisterIndex(indexer.Name); + indexer.CreateIndex(); + rebuilder.Populate(indexer); - var searcher = indexer.GetSearcher(); var numberSortedCriteria = searcher.CreateCriteria() @@ -80,12 +86,12 @@ namespace Umbraco.Tests.UmbracoExamine } } - private bool IsSortedByNumber(IEnumerable results) + private bool IsSortedByNumber(IEnumerable results) { var currentSort = 0; foreach (var searchResult in results) { - var sort = int.Parse(searchResult.Fields["sortOrder"]); + var sort = int.Parse(searchResult.Values["sortOrder"]); if (currentSort >= sort) { return false; diff --git a/src/Umbraco.Tests/UmbracoExamine/TestDataService.cs b/src/Umbraco.Tests/UmbracoExamine/TestDataService.cs deleted file mode 100644 index 856c3e99aa..0000000000 --- a/src/Umbraco.Tests/UmbracoExamine/TestDataService.cs +++ /dev/null @@ -1,32 +0,0 @@ -//using System.IO; -//using Umbraco.Tests.TestHelpers; -//using UmbracoExamine.DataServices; - -//namespace Umbraco.Tests.UmbracoExamine -//{ -// public class TestDataService : IDataService -// { - -// public TestDataService() -// { -// ContentService = new TestContentService(); -// LogService = new TestLogService(); -// MediaService = new TestMediaService(); -// } - -// #region IDataService Members - -// public IContentService ContentService { get; internal set; } - -// public ILogService LogService { get; internal set; } - -// public IMediaService MediaService { get; internal set; } - -// public string MapPath(string virtualPath) -// { -// return new DirectoryInfo(TestHelper.CurrentAssemblyDirectory) + "\\" + virtualPath.Replace("/", "\\"); -// } - -// #endregion -// } -//} diff --git a/src/Umbraco.Tests/UmbracoExamine/UmbracoContentValueSetValidatorTests.cs b/src/Umbraco.Tests/UmbracoExamine/UmbracoContentValueSetValidatorTests.cs new file mode 100644 index 0000000000..934dd34503 --- /dev/null +++ b/src/Umbraco.Tests/UmbracoExamine/UmbracoContentValueSetValidatorTests.cs @@ -0,0 +1,300 @@ +using Examine; +using NUnit.Framework; +using Umbraco.Examine; +using Moq; +using Umbraco.Core.Services; +using System.Collections.Generic; +using Umbraco.Core; +using Umbraco.Core.Models; +using System; +using System.Linq; + +namespace Umbraco.Tests.UmbracoExamine +{ + [TestFixture] + public class UmbracoContentValueSetValidatorTests + { + [Test] + public void Invalid_Category() + { + var validator = new ContentValueSetValidator(false, true, Mock.Of()); + + var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + + result = validator.Validate(ValueSet.FromObject("777", IndexTypes.Media, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + + result = validator.Validate(ValueSet.FromObject("555", "invalid-category", new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + } + + [Test] + public void Must_Have_Path() + { + var validator = new ContentValueSetValidator(false, true, Mock.Of()); + + var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + } + + [Test] + public void Parent_Id() + { + var validator = new ContentValueSetValidator(false, true, Mock.Of(), 555); + + var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Filtered, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,444" })); + Assert.AreEqual(ValueSetValidationResult.Filtered, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555,777" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555,777,999" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + } + + [Test] + public void Inclusion_Field_List() + { + var validator = new ValueSetValidator(null, null, + new[] { "hello", "world" }, + null); + + var valueSet = ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555", world = "your oyster" }); + var result = validator.Validate(valueSet); + Assert.AreEqual(ValueSetValidationResult.Filtered, result); + + Assert.IsFalse(valueSet.Values.ContainsKey("path")); + Assert.IsTrue(valueSet.Values.ContainsKey("hello")); + Assert.IsTrue(valueSet.Values.ContainsKey("world")); + } + + [Test] + public void Exclusion_Field_List() + { + var validator = new ValueSetValidator(null, null, + null, + new[] { "hello", "world" }); + + var valueSet = ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555", world = "your oyster" }); + var result = validator.Validate(valueSet); + Assert.AreEqual(ValueSetValidationResult.Filtered, result); + + Assert.IsTrue(valueSet.Values.ContainsKey("path")); + Assert.IsFalse(valueSet.Values.ContainsKey("hello")); + Assert.IsFalse(valueSet.Values.ContainsKey("world")); + } + + [Test] + public void Inclusion_Exclusion_Field_List() + { + var validator = new ValueSetValidator(null, null, + new[] { "hello", "world" }, + new[] { "world" }); + + var valueSet = ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555", world = "your oyster" }); + var result = validator.Validate(valueSet); + Assert.AreEqual(ValueSetValidationResult.Filtered, result); + + Assert.IsFalse(valueSet.Values.ContainsKey("path")); + Assert.IsTrue(valueSet.Values.ContainsKey("hello")); + Assert.IsFalse(valueSet.Values.ContainsKey("world")); + } + + [Test] + public void Inclusion_Type_List() + { + var validator = new ContentValueSetValidator(false, true, Mock.Of(), + includeItemTypes: new List { "include-content" }); + + var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "include-content", new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + } + + [Test] + public void Exclusion_Type_List() + { + var validator = new ContentValueSetValidator(false, true, Mock.Of(), + excludeItemTypes: new List { "exclude-content" }); + + var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "exclude-content", new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + } + + [Test] + public void Inclusion_Exclusion_Type_List() + { + var validator = new ContentValueSetValidator(false, true, Mock.Of(), + includeItemTypes: new List { "include-content", "exclude-content" }, + excludeItemTypes: new List { "exclude-content" }); + + var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "test-content", new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "exclude-content", new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, "include-content", new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + } + + [Test] + public void Recycle_Bin_Content() + { + var validator = new ContentValueSetValidator(true, false, Mock.Of()); + + var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,-20,555" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,-20,555,777" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(new ValueSet("555", IndexTypes.Content, + new Dictionary + { + ["hello"] = "world", + ["path"] = "-1,555", + [UmbracoExamineIndexer.PublishedFieldName] = 1 + })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + } + + [Test] + public void Recycle_Bin_Media() + { + var validator = new ContentValueSetValidator(true, false, Mock.Of()); + + var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Media, new { hello = "world", path = "-1,-21,555" })); + Assert.AreEqual(ValueSetValidationResult.Filtered, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Media, new { hello = "world", path = "-1,-21,555,777" })); + Assert.AreEqual(ValueSetValidationResult.Filtered, result); + + result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Media, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + + } + + [Test] + public void Published_Only() + { + var validator = new ContentValueSetValidator(true, true, Mock.Of()); + + var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(new ValueSet("555", IndexTypes.Content, + new Dictionary + { + ["hello"] = "world", + ["path"] = "-1,555", + [UmbracoExamineIndexer.PublishedFieldName] = 0 + })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(new ValueSet("555", IndexTypes.Content, + new Dictionary + { + ["hello"] = "world", + ["path"] = "-1,555", + [UmbracoExamineIndexer.PublishedFieldName] = 1 + })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + } + + [Test] + public void Published_Only_With_Variants() + { + var validator = new ContentValueSetValidator(true, true, Mock.Of()); + + var result = validator.Validate(new ValueSet("555", IndexTypes.Content, + new Dictionary + { + ["hello"] = "world", + ["path"] = "-1,555", + [UmbracoContentIndexer.VariesByCultureFieldName] = 1, + [UmbracoExamineIndexer.PublishedFieldName] = 0 + })); + Assert.AreEqual(ValueSetValidationResult.Failed, result); + + result = validator.Validate(new ValueSet("555", IndexTypes.Content, + new Dictionary + { + ["hello"] = "world", + ["path"] = "-1,555", + [UmbracoContentIndexer.VariesByCultureFieldName] = 1, + [UmbracoExamineIndexer.PublishedFieldName] = 1 + })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + + var valueSet = new ValueSet("555", IndexTypes.Content, + new Dictionary + { + ["hello"] = "world", + ["path"] = "-1,555", + [UmbracoContentIndexer.VariesByCultureFieldName] = 1, + [$"{UmbracoExamineIndexer.PublishedFieldName}_en-us"] = 1, + ["hello_en-us"] = "world", + ["title_en-us"] = "my title", + [$"{UmbracoExamineIndexer.PublishedFieldName}_es-es"] = 0, + ["hello_es-ES"] = "world", + ["title_es-ES"] = "my title", + [UmbracoExamineIndexer.PublishedFieldName] = 1 + }); + Assert.AreEqual(10, valueSet.Values.Count()); + Assert.IsTrue(valueSet.Values.ContainsKey($"{UmbracoExamineIndexer.PublishedFieldName}_es-es")); + Assert.IsTrue(valueSet.Values.ContainsKey("hello_es-ES")); + Assert.IsTrue(valueSet.Values.ContainsKey("title_es-ES")); + + result = validator.Validate(valueSet); + Assert.AreEqual(ValueSetValidationResult.Filtered, result); + + Assert.AreEqual(7, valueSet.Values.Count()); //filtered to 7 values (removes es-es values) + Assert.IsFalse(valueSet.Values.ContainsKey($"{UmbracoExamineIndexer.PublishedFieldName}_es-es")); + Assert.IsFalse(valueSet.Values.ContainsKey("hello_es-ES")); + Assert.IsFalse(valueSet.Values.ContainsKey("title_es-ES")); + } + + [Test] + public void Non_Protected() + { + var publicAccessService = new Mock(); + publicAccessService.Setup(x => x.IsProtected("-1,555")) + .Returns(Attempt.Succeed(new PublicAccessEntry(Guid.NewGuid(), 555, 444, 333, Enumerable.Empty()))); + publicAccessService.Setup(x => x.IsProtected("-1,777")) + .Returns(Attempt.Fail()); + var validator = new ContentValueSetValidator(false, false, publicAccessService.Object); + + var result = validator.Validate(ValueSet.FromObject("555", IndexTypes.Content, new { hello = "world", path = "-1,555" })); + Assert.AreEqual(ValueSetValidationResult.Filtered, result); + + result = validator.Validate(ValueSet.FromObject("777", IndexTypes.Content, new { hello = "world", path = "-1,777" })); + Assert.AreEqual(ValueSetValidationResult.Valid, result); + } + } +} diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index 4186c56636..81f338da87 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -125,12 +125,10 @@ namespace Umbraco.Tests.Web.Mvc //return mock of IPublishedContent for any call to GetById Mock.Of(content => content.Id == 2)), Mock.Of(), - Mock.Of(), Mock.Of(), Mock.Of(), new MembershipHelper(umbracoContext, Mock.Of(), Mock.Of()), - new ServiceContext(), - CacheHelper.CreateDisabledCacheHelper()); + new ServiceContext()); var ctrl = new TestSurfaceController { UmbracoContext = umbracoContext, Umbraco = helper }; var result = ctrl.GetContent(2) as PublishedContentResult; diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index dd4ebe4e8b..cfba283cc7 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -8,7 +8,7 @@ "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", "dev": true, "requires": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "7.0.0" } }, "@babel/core": { @@ -17,20 +17,20 @@ "integrity": "sha512-Hz6PJT6e44iUNpAn8AoyAs6B3bl60g7MJQaI0rZEar6ECzh6+srYO1xlIdssio34mPaUtAb1y+XlkkSJzok3yw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", - "@babel/helpers": "^7.1.5", - "@babel/parser": "^7.1.6", - "@babel/template": "^7.1.2", - "@babel/traverse": "^7.1.6", - "@babel/types": "^7.1.6", - "convert-source-map": "^1.1.0", - "debug": "^4.1.0", - "json5": "^2.1.0", - "lodash": "^4.17.10", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" + "@babel/code-frame": "7.0.0", + "@babel/generator": "7.1.6", + "@babel/helpers": "7.1.5", + "@babel/parser": "7.1.6", + "@babel/template": "7.1.2", + "@babel/traverse": "7.1.6", + "@babel/types": "7.1.6", + "convert-source-map": "1.6.0", + "debug": "4.1.0", + "json5": "2.1.0", + "lodash": "4.17.11", + "resolve": "1.8.1", + "semver": "5.6.0", + "source-map": "0.5.7" } }, "@babel/generator": { @@ -39,11 +39,11 @@ "integrity": "sha512-brwPBtVvdYdGxtenbQgfCdDPmtkmUBZPjUoK5SXJEBuHaA5BCubh9ly65fzXz7R6o5rA76Rs22ES8Z+HCc0YIQ==", "dev": true, "requires": { - "@babel/types": "^7.1.6", - "jsesc": "^2.5.1", - "lodash": "^4.17.10", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" + "@babel/types": "7.1.6", + "jsesc": "2.5.2", + "lodash": "4.17.11", + "source-map": "0.5.7", + "trim-right": "1.0.1" } }, "@babel/helper-annotate-as-pure": { @@ -52,7 +52,7 @@ "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.6" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { @@ -61,8 +61,8 @@ "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-explode-assignable-expression": "7.1.0", + "@babel/types": "7.1.6" } }, "@babel/helper-call-delegate": { @@ -71,9 +71,9 @@ "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-hoist-variables": "7.0.0", + "@babel/traverse": "7.1.6", + "@babel/types": "7.1.6" } }, "@babel/helper-define-map": { @@ -82,9 +82,9 @@ "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" + "@babel/helper-function-name": "7.1.0", + "@babel/types": "7.1.6", + "lodash": "4.17.11" } }, "@babel/helper-explode-assignable-expression": { @@ -93,8 +93,8 @@ "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", "dev": true, "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/traverse": "7.1.6", + "@babel/types": "7.1.6" } }, "@babel/helper-function-name": { @@ -103,9 +103,9 @@ "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-get-function-arity": "7.0.0", + "@babel/template": "7.1.2", + "@babel/types": "7.1.6" } }, "@babel/helper-get-function-arity": { @@ -114,7 +114,7 @@ "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.6" } }, "@babel/helper-hoist-variables": { @@ -123,7 +123,7 @@ "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.6" } }, "@babel/helper-member-expression-to-functions": { @@ -132,7 +132,7 @@ "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.6" } }, "@babel/helper-module-imports": { @@ -141,7 +141,7 @@ "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.6" } }, "@babel/helper-module-transforms": { @@ -150,12 +150,12 @@ "integrity": "sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" + "@babel/helper-module-imports": "7.0.0", + "@babel/helper-simple-access": "7.1.0", + "@babel/helper-split-export-declaration": "7.0.0", + "@babel/template": "7.1.2", + "@babel/types": "7.1.6", + "lodash": "4.17.11" } }, "@babel/helper-optimise-call-expression": { @@ -164,7 +164,7 @@ "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.6" } }, "@babel/helper-plugin-utils": { @@ -179,7 +179,7 @@ "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } }, "@babel/helper-remap-async-to-generator": { @@ -188,11 +188,11 @@ "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-annotate-as-pure": "7.0.0", + "@babel/helper-wrap-function": "7.1.0", + "@babel/template": "7.1.2", + "@babel/traverse": "7.1.6", + "@babel/types": "7.1.6" } }, "@babel/helper-replace-supers": { @@ -201,10 +201,10 @@ "integrity": "sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-member-expression-to-functions": "7.0.0", + "@babel/helper-optimise-call-expression": "7.0.0", + "@babel/traverse": "7.1.6", + "@babel/types": "7.1.6" } }, "@babel/helper-simple-access": { @@ -213,8 +213,8 @@ "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", "dev": true, "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/template": "7.1.2", + "@babel/types": "7.1.6" } }, "@babel/helper-split-export-declaration": { @@ -223,7 +223,7 @@ "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.6" } }, "@babel/helper-wrap-function": { @@ -232,10 +232,10 @@ "integrity": "sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-function-name": "7.1.0", + "@babel/template": "7.1.2", + "@babel/traverse": "7.1.6", + "@babel/types": "7.1.6" } }, "@babel/helpers": { @@ -244,9 +244,9 @@ "integrity": "sha512-2jkcdL02ywNBry1YNFAH/fViq4fXG0vdckHqeJk+75fpQ2OH+Az6076tX/M0835zA45E0Cqa6pV5Kiv9YOqjEg==", "dev": true, "requires": { - "@babel/template": "^7.1.2", - "@babel/traverse": "^7.1.5", - "@babel/types": "^7.1.5" + "@babel/template": "7.1.2", + "@babel/traverse": "7.1.6", + "@babel/types": "7.1.6" } }, "@babel/highlight": { @@ -255,9 +255,9 @@ "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" + "chalk": "2.4.1", + "esutils": "2.0.2", + "js-tokens": "4.0.0" } }, "@babel/parser": { @@ -272,9 +272,9 @@ "integrity": "sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-remap-async-to-generator": "7.1.0", + "@babel/plugin-syntax-async-generators": "7.0.0" } }, "@babel/plugin-proposal-json-strings": { @@ -283,8 +283,8 @@ "integrity": "sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/plugin-syntax-json-strings": "7.0.0" } }, "@babel/plugin-proposal-object-rest-spread": { @@ -293,8 +293,8 @@ "integrity": "sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/plugin-syntax-object-rest-spread": "7.0.0" } }, "@babel/plugin-proposal-optional-catch-binding": { @@ -303,8 +303,8 @@ "integrity": "sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "7.0.0" } }, "@babel/plugin-proposal-unicode-property-regex": { @@ -313,9 +313,9 @@ "integrity": "sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.2.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-regex": "7.0.0", + "regexpu-core": "4.2.0" } }, "@babel/plugin-syntax-async-generators": { @@ -324,7 +324,7 @@ "integrity": "sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-syntax-json-strings": { @@ -333,7 +333,7 @@ "integrity": "sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-syntax-object-rest-spread": { @@ -342,7 +342,7 @@ "integrity": "sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-syntax-optional-catch-binding": { @@ -351,7 +351,7 @@ "integrity": "sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-arrow-functions": { @@ -360,7 +360,7 @@ "integrity": "sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-async-to-generator": { @@ -369,9 +369,9 @@ "integrity": "sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" + "@babel/helper-module-imports": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-remap-async-to-generator": "7.1.0" } }, "@babel/plugin-transform-block-scoped-functions": { @@ -380,7 +380,7 @@ "integrity": "sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-block-scoping": { @@ -389,8 +389,8 @@ "integrity": "sha512-jlYcDrz+5ayWC7mxgpn1Wj8zj0mmjCT2w0mPIMSwO926eXBRxpEgoN/uQVRBfjtr8ayjcmS+xk2G1jaP8JjMJQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.10" + "@babel/helper-plugin-utils": "7.0.0", + "lodash": "4.17.11" } }, "@babel/plugin-transform-classes": { @@ -399,14 +399,14 @@ "integrity": "sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.1.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "globals": "^11.1.0" + "@babel/helper-annotate-as-pure": "7.0.0", + "@babel/helper-define-map": "7.1.0", + "@babel/helper-function-name": "7.1.0", + "@babel/helper-optimise-call-expression": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-replace-supers": "7.1.0", + "@babel/helper-split-export-declaration": "7.0.0", + "globals": "11.9.0" } }, "@babel/plugin-transform-computed-properties": { @@ -415,7 +415,7 @@ "integrity": "sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-destructuring": { @@ -424,7 +424,7 @@ "integrity": "sha512-Mb9M4DGIOspH1ExHOUnn2UUXFOyVTiX84fXCd+6B5iWrQg/QMeeRmSwpZ9lnjYLSXtZwiw80ytVMr3zue0ucYw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-dotall-regex": { @@ -433,9 +433,9 @@ "integrity": "sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-regex": "7.0.0", + "regexpu-core": "4.2.0" } }, "@babel/plugin-transform-duplicate-keys": { @@ -444,7 +444,7 @@ "integrity": "sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-exponentiation-operator": { @@ -453,8 +453,8 @@ "integrity": "sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-builder-binary-assignment-operator-visitor": "7.1.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-for-of": { @@ -463,7 +463,7 @@ "integrity": "sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-function-name": { @@ -472,8 +472,8 @@ "integrity": "sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-function-name": "7.1.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-literals": { @@ -482,7 +482,7 @@ "integrity": "sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-modules-amd": { @@ -491,8 +491,8 @@ "integrity": "sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-module-transforms": "7.1.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-modules-commonjs": { @@ -501,9 +501,9 @@ "integrity": "sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" + "@babel/helper-module-transforms": "7.1.0", + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-simple-access": "7.1.0" } }, "@babel/plugin-transform-modules-systemjs": { @@ -512,8 +512,8 @@ "integrity": "sha512-PvTxgjxQAq4pvVUZF3mD5gEtVDuId8NtWkJsZLEJZMZAW3TvgQl1pmydLLN1bM8huHFVVU43lf0uvjQj9FRkKw==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-hoist-variables": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-modules-umd": { @@ -522,8 +522,8 @@ "integrity": "sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-module-transforms": "7.1.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-new-target": { @@ -532,7 +532,7 @@ "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-object-super": { @@ -541,8 +541,8 @@ "integrity": "sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-replace-supers": "7.1.0" } }, "@babel/plugin-transform-parameters": { @@ -551,9 +551,9 @@ "integrity": "sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw==", "dev": true, "requires": { - "@babel/helper-call-delegate": "^7.1.0", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-call-delegate": "7.1.0", + "@babel/helper-get-function-arity": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-regenerator": { @@ -562,7 +562,7 @@ "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", "dev": true, "requires": { - "regenerator-transform": "^0.13.3" + "regenerator-transform": "0.13.3" } }, "@babel/plugin-transform-shorthand-properties": { @@ -571,7 +571,7 @@ "integrity": "sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-spread": { @@ -580,7 +580,7 @@ "integrity": "sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-sticky-regex": { @@ -589,8 +589,8 @@ "integrity": "sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-regex": "7.0.0" } }, "@babel/plugin-transform-template-literals": { @@ -599,8 +599,8 @@ "integrity": "sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-annotate-as-pure": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-typeof-symbol": { @@ -609,7 +609,7 @@ "integrity": "sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-unicode-regex": { @@ -618,9 +618,9 @@ "integrity": "sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-regex": "7.0.0", + "regexpu-core": "4.2.0" } }, "@babel/preset-env": { @@ -629,47 +629,47 @@ "integrity": "sha512-YIBfpJNQMBkb6MCkjz/A9J76SNCSuGVamOVBgoUkLzpJD/z8ghHi9I42LQ4pulVX68N/MmImz6ZTixt7Azgexw==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.1.0", - "@babel/plugin-proposal-json-strings": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.0.0", - "@babel/plugin-syntax-async-generators": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.1.0", - "@babel/plugin-transform-block-scoped-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.1.5", - "@babel/plugin-transform-classes": "^7.1.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-dotall-regex": "^7.0.0", - "@babel/plugin-transform-duplicate-keys": "^7.0.0", - "@babel/plugin-transform-exponentiation-operator": "^7.1.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.1.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-amd": "^7.1.0", - "@babel/plugin-transform-modules-commonjs": "^7.1.0", - "@babel/plugin-transform-modules-systemjs": "^7.0.0", - "@babel/plugin-transform-modules-umd": "^7.1.0", - "@babel/plugin-transform-new-target": "^7.0.0", - "@babel/plugin-transform-object-super": "^7.1.0", - "@babel/plugin-transform-parameters": "^7.1.0", - "@babel/plugin-transform-regenerator": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "@babel/plugin-transform-typeof-symbol": "^7.0.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "browserslist": "^4.1.0", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.3.0" + "@babel/helper-module-imports": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0", + "@babel/plugin-proposal-async-generator-functions": "7.1.0", + "@babel/plugin-proposal-json-strings": "7.0.0", + "@babel/plugin-proposal-object-rest-spread": "7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "7.0.0", + "@babel/plugin-syntax-async-generators": "7.0.0", + "@babel/plugin-syntax-object-rest-spread": "7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "7.0.0", + "@babel/plugin-transform-arrow-functions": "7.0.0", + "@babel/plugin-transform-async-to-generator": "7.1.0", + "@babel/plugin-transform-block-scoped-functions": "7.0.0", + "@babel/plugin-transform-block-scoping": "7.1.5", + "@babel/plugin-transform-classes": "7.1.0", + "@babel/plugin-transform-computed-properties": "7.0.0", + "@babel/plugin-transform-destructuring": "7.1.3", + "@babel/plugin-transform-dotall-regex": "7.0.0", + "@babel/plugin-transform-duplicate-keys": "7.0.0", + "@babel/plugin-transform-exponentiation-operator": "7.1.0", + "@babel/plugin-transform-for-of": "7.0.0", + "@babel/plugin-transform-function-name": "7.1.0", + "@babel/plugin-transform-literals": "7.0.0", + "@babel/plugin-transform-modules-amd": "7.1.0", + "@babel/plugin-transform-modules-commonjs": "7.1.0", + "@babel/plugin-transform-modules-systemjs": "7.1.3", + "@babel/plugin-transform-modules-umd": "7.1.0", + "@babel/plugin-transform-new-target": "7.0.0", + "@babel/plugin-transform-object-super": "7.1.0", + "@babel/plugin-transform-parameters": "7.1.0", + "@babel/plugin-transform-regenerator": "7.0.0", + "@babel/plugin-transform-shorthand-properties": "7.0.0", + "@babel/plugin-transform-spread": "7.0.0", + "@babel/plugin-transform-sticky-regex": "7.0.0", + "@babel/plugin-transform-template-literals": "7.0.0", + "@babel/plugin-transform-typeof-symbol": "7.0.0", + "@babel/plugin-transform-unicode-regex": "7.0.0", + "browserslist": "4.3.5", + "invariant": "2.2.4", + "js-levenshtein": "1.1.4", + "semver": "5.6.0" } }, "@babel/template": { @@ -678,9 +678,9 @@ "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/code-frame": "7.0.0", + "@babel/parser": "7.1.6", + "@babel/types": "7.1.6" } }, "@babel/traverse": { @@ -689,15 +689,15 @@ "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.6", - "@babel/types": "^7.1.6", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.10" + "@babel/code-frame": "7.0.0", + "@babel/generator": "7.1.6", + "@babel/helper-function-name": "7.1.0", + "@babel/helper-split-export-declaration": "7.0.0", + "@babel/parser": "7.1.6", + "@babel/types": "7.1.6", + "debug": "4.1.0", + "globals": "11.9.0", + "lodash": "4.17.11" } }, "@babel/types": { @@ -706,9 +706,9 @@ "integrity": "sha512-DMiUzlY9DSjVsOylJssxLHSgj6tWM9PRFJOGW/RaOglVOK9nzTxoOMfTfRQXGUCUQ/HmlG2efwC+XqUEJ5ay4w==", "dev": true, "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.10", - "to-fast-properties": "^2.0.0" + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "2.0.0" } }, "@mrmlnc/readdir-enhanced": { @@ -717,8 +717,8 @@ "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", "dev": true, "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" + "call-me-maybe": "1.0.1", + "glob-to-regexp": "0.3.0" } }, "@nodelib/fs.stat": { @@ -745,7 +745,7 @@ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "~2.1.18", + "mime-types": "2.1.21", "negotiator": "0.6.1" } }, @@ -755,20 +755,20 @@ "integrity": "sha512-3OOR92FTc2p5/EcOzPcXp+Cbo+3C15nV9RXHlOUBCBpHhcB+0frbSNR9ehED/o7sTcyGVtqGJpguToEdlXhD0w==", "dev": true, "requires": { - "convert-source-map": "^1.5.0", - "glob": "^7.0.5", - "indx": "^0.2.3", - "lodash.clone": "^4.3.2", - "lodash.defaults": "^4.0.1", - "lodash.flatten": "^4.2.0", - "lodash.merge": "^4.4.0", - "lodash.partialright": "^4.1.4", - "lodash.pick": "^4.2.1", - "lodash.uniq": "^4.3.0", - "resolve": "^1.5.0", - "semver": "^5.3.0", - "uglify-js": "^2.8.22", - "when": "^3.7.8" + "convert-source-map": "1.6.0", + "glob": "7.1.3", + "indx": "0.2.3", + "lodash.clone": "4.5.0", + "lodash.defaults": "4.2.0", + "lodash.flatten": "4.4.0", + "lodash.merge": "4.6.1", + "lodash.partialright": "4.2.1", + "lodash.pick": "4.4.0", + "lodash.uniq": "4.5.0", + "resolve": "1.8.1", + "semver": "5.6.0", + "uglify-js": "2.8.29", + "when": "3.7.8" }, "dependencies": { "glob": { @@ -777,12 +777,12 @@ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": 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" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" } }, "minimatch": { @@ -791,7 +791,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } } } @@ -825,10 +825,10 @@ "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", "dev": true, "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" + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.2.2" } }, "align-text": { @@ -837,9 +837,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" }, "dependencies": { "kind-of": { @@ -848,7 +848,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -885,7 +885,7 @@ "resolved": "https://registry.npmjs.org/angular-dynamic-locale/-/angular-dynamic-locale-0.1.37.tgz", "integrity": "sha512-m5Kyk8W8/mOZSqRxuByOwHBjv8labLBAgvl0Z3iQx2xT/tWCqb94imKUPwumudszdPDjxeopwyucQvm8Sw7ogw==", "requires": { - "@types/angular": "^1.6.25" + "@types/angular": "1.6.51" } }, "angular-i18n": { @@ -928,9 +928,9 @@ "resolved": "https://registry.npmjs.org/angular-ui-sortable/-/angular-ui-sortable-0.19.0.tgz", "integrity": "sha512-u/uc981Nzg4XN1bMU9qKleMTSt7F1XjMWnyGw6gxPLIeQeLZm8jWNy7tj8y2r2HmvzXFbQVq2z6rObznFKAekQ==", "requires": { - "angular": ">=1.2.x", - "jquery": ">=3.1.x", - "jquery-ui-dist": ">=1.12.x" + "angular": "1.7.5", + "jquery": "3.3.1", + "jquery-ui-dist": "1.12.1" } }, "animejs": { @@ -944,7 +944,7 @@ "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "dev": true, "requires": { - "ansi-wrap": "^0.1.0" + "ansi-wrap": "0.1.0" } }, "ansi-cyan": { @@ -992,7 +992,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.3" } }, "ansi-wrap": { @@ -1007,8 +1007,8 @@ "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" + "micromatch": "2.3.11", + "normalize-path": "2.1.1" }, "dependencies": { "arr-diff": { @@ -1017,7 +1017,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -1032,9 +1032,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.3" } }, "expand-brackets": { @@ -1043,7 +1043,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -1052,7 +1052,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "is-extglob": { @@ -1067,7 +1067,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "kind-of": { @@ -1076,7 +1076,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -1085,19 +1085,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } } } @@ -1116,7 +1116,7 @@ "dev": true, "optional": true, "requires": { - "file-type": "^4.2.0" + "file-type": "4.4.0" }, "dependencies": { "file-type": { @@ -1140,7 +1140,7 @@ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "sprintf-js": "1.0.3" } }, "arr-diff": { @@ -1191,7 +1191,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "^1.0.1" + "array-uniq": "1.0.3" } }, "array-uniq": { @@ -1231,7 +1231,7 @@ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "dev": true, "requires": { - "safer-buffer": "~2.1.0" + "safer-buffer": "2.1.2" } }, "assert-plus": { @@ -1282,12 +1282,12 @@ "integrity": "sha512-DY9gOh8z3tnCbJ13JIWaeQsoYncTGdsrgCceBaQSIL4nvdrLxgbRSBPevg2XbX7u4QCSfLheSJEEIUUSlkbx6Q==", "dev": true, "requires": { - "browserslist": "^4.3.3", - "caniuse-lite": "^1.0.30000898", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^7.0.5", - "postcss-value-parser": "^3.3.1" + "browserslist": "4.3.5", + "caniuse-lite": "1.0.30000913", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "aws-sign2": { @@ -1320,13 +1320,13 @@ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "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" + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" }, "dependencies": { "define-property": { @@ -1335,7 +1335,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "is-accessor-descriptor": { @@ -1344,7 +1344,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -1353,7 +1353,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -1362,9 +1362,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -1399,7 +1399,7 @@ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "requires": { - "tweetnacl": "^0.14.3" + "tweetnacl": "0.14.5" } }, "beeper": { @@ -1424,11 +1424,11 @@ "dev": true, "optional": true, "requires": { - "decompress": "^4.0.0", - "download": "^6.2.2", - "execa": "^0.7.0", - "p-map-series": "^1.0.0", - "tempfile": "^2.0.0" + "decompress": "4.2.0", + "download": "6.2.5", + "execa": "0.7.0", + "p-map-series": "1.0.0", + "tempfile": "2.0.0" } }, "bin-check": { @@ -1438,8 +1438,8 @@ "dev": true, "optional": true, "requires": { - "execa": "^0.7.0", - "executable": "^4.1.0" + "execa": "0.7.0", + "executable": "4.1.1" } }, "bin-version": { @@ -1449,8 +1449,8 @@ "dev": true, "optional": true, "requires": { - "execa": "^1.0.0", - "find-versions": "^3.0.0" + "execa": "1.0.0", + "find-versions": "3.0.0" }, "dependencies": { "execa": { @@ -1460,13 +1460,13 @@ "dev": true, "optional": true, "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" + "cross-spawn": "6.0.5", + "get-stream": "4.1.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" } }, "get-stream": { @@ -1476,7 +1476,7 @@ "dev": true, "optional": true, "requires": { - "pump": "^3.0.0" + "pump": "3.0.0" } } } @@ -1488,9 +1488,9 @@ "dev": true, "optional": true, "requires": { - "bin-version": "^3.0.0", - "semver": "^5.6.0", - "semver-truncate": "^1.1.2" + "bin-version": "3.0.0", + "semver": "5.6.0", + "semver-truncate": "1.1.2" } }, "bin-wrapper": { @@ -1500,12 +1500,12 @@ "dev": true, "optional": true, "requires": { - "bin-check": "^4.1.0", - "bin-version-check": "^4.0.0", - "download": "^7.1.0", - "import-lazy": "^3.1.0", - "os-filter-obj": "^2.0.0", - "pify": "^4.0.1" + "bin-check": "4.1.0", + "bin-version-check": "4.0.0", + "download": "7.1.0", + "import-lazy": "3.1.0", + "os-filter-obj": "2.0.0", + "pify": "4.0.1" }, "dependencies": { "download": { @@ -1515,18 +1515,18 @@ "dev": true, "optional": true, "requires": { - "archive-type": "^4.0.0", - "caw": "^2.0.1", - "content-disposition": "^0.5.2", - "decompress": "^4.2.0", - "ext-name": "^5.0.0", - "file-type": "^8.1.0", - "filenamify": "^2.0.0", - "get-stream": "^3.0.0", - "got": "^8.3.1", - "make-dir": "^1.2.0", - "p-event": "^2.1.0", - "pify": "^3.0.0" + "archive-type": "4.0.0", + "caw": "2.0.1", + "content-disposition": "0.5.2", + "decompress": "4.2.0", + "ext-name": "5.0.0", + "file-type": "8.1.0", + "filenamify": "2.1.0", + "get-stream": "3.0.0", + "got": "8.3.2", + "make-dir": "1.3.0", + "p-event": "2.1.0", + "pify": "3.0.0" }, "dependencies": { "pify": { @@ -1545,23 +1545,23 @@ "dev": true, "optional": true, "requires": { - "@sindresorhus/is": "^0.7.0", - "cacheable-request": "^2.1.1", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "into-stream": "^3.1.0", - "is-retry-allowed": "^1.1.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "mimic-response": "^1.0.0", - "p-cancelable": "^0.4.0", - "p-timeout": "^2.0.1", - "pify": "^3.0.0", - "safe-buffer": "^5.1.1", - "timed-out": "^4.0.1", - "url-parse-lax": "^3.0.0", - "url-to-options": "^1.0.1" + "@sindresorhus/is": "0.7.0", + "cacheable-request": "2.1.4", + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "into-stream": "3.1.0", + "is-retry-allowed": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "mimic-response": "1.0.1", + "p-cancelable": "0.4.1", + "p-timeout": "2.0.1", + "pify": "3.0.0", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "3.0.0", + "url-to-options": "1.0.1" }, "dependencies": { "pify": { @@ -1587,7 +1587,7 @@ "dev": true, "optional": true, "requires": { - "p-timeout": "^2.0.1" + "p-timeout": "2.0.1" } }, "p-timeout": { @@ -1596,7 +1596,7 @@ "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", "dev": true, "requires": { - "p-finally": "^1.0.0" + "p-finally": "1.0.0" } }, "pify": { @@ -1620,7 +1620,7 @@ "dev": true, "optional": true, "requires": { - "prepend-http": "^2.0.0" + "prepend-http": "2.0.0" } } } @@ -1637,8 +1637,8 @@ "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", "dev": true, "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" + "readable-stream": "2.3.6", + "safe-buffer": "5.1.2" }, "dependencies": { "isarray": { @@ -1653,13 +1653,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -1668,7 +1668,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -1691,10 +1691,10 @@ "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", "dev": true, "requires": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" + "continuable-cache": "0.3.1", + "error": "7.0.2", + "raw-body": "1.1.7", + "safe-json-parse": "1.0.1" } }, "body-parser": { @@ -1704,15 +1704,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "~1.0.4", + "content-type": "1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", + "depd": "1.1.2", + "http-errors": "1.6.3", "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", + "on-finished": "2.3.0", "qs": "6.5.2", "raw-body": "2.3.3", - "type-is": "~1.6.16" + "type-is": "1.6.16" }, "dependencies": { "bytes": { @@ -1736,7 +1736,7 @@ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } }, "ms": { @@ -1781,8 +1781,8 @@ "resolved": "https://registry.npmjs.org/bootstrap-social/-/bootstrap-social-5.1.1.tgz", "integrity": "sha1-dTDGeK31bPj60/qCwp1NPl0CdQE=", "requires": { - "bootstrap": "~3", - "font-awesome": "~4.7" + "bootstrap": "3.3.7", + "font-awesome": "4.7.0" } }, "brace-expansion": { @@ -1791,7 +1791,7 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, @@ -1801,16 +1801,16 @@ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "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" + "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.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" }, "dependencies": { "extend-shallow": { @@ -1819,7 +1819,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -1830,9 +1830,9 @@ "integrity": "sha512-z9ZhGc3d9e/sJ9dIx5NFXkKoaiQTnrvrMsN3R1fGb1tkWWNSz12UewJn9TNxGo1l7J23h0MRaPmk7jfeTZYs1w==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000912", - "electron-to-chromium": "^1.3.86", - "node-releases": "^1.0.5" + "caniuse-lite": "1.0.30000913", + "electron-to-chromium": "1.3.87", + "node-releases": "1.0.5" } }, "buffer": { @@ -1842,8 +1842,8 @@ "dev": true, "requires": { "base64-js": "0.0.8", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "ieee754": "1.1.12", + "isarray": "1.0.0" }, "dependencies": { "isarray": { @@ -1860,8 +1860,8 @@ "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", "dev": true, "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" } }, "buffer-alloc-unsafe": { @@ -1894,7 +1894,7 @@ "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", "dev": true, "requires": { - "readable-stream": "^1.0.33" + "readable-stream": "1.1.14" } }, "builtin-modules": { @@ -1915,15 +1915,15 @@ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "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" + "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" } }, "cacheable-request": { @@ -1956,9 +1956,9 @@ "dev": true, "optional": true, "requires": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" + "prepend-http": "2.0.0", + "query-string": "5.1.1", + "sort-keys": "2.0.0" } }, "prepend-http": { @@ -1975,7 +1975,7 @@ "dev": true, "optional": true, "requires": { - "is-plain-obj": "^1.0.0" + "is-plain-obj": "1.1.0" } } } @@ -1992,7 +1992,7 @@ "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", "dev": true, "requires": { - "callsites": "^2.0.0" + "callsites": "2.0.0" } }, "caller-path": { @@ -2001,7 +2001,7 @@ "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", "dev": true, "requires": { - "caller-callsite": "^2.0.0" + "caller-callsite": "2.0.0" } }, "callsite": { @@ -2028,8 +2028,8 @@ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" + "camelcase": "2.1.1", + "map-obj": "1.0.1" } }, "caniuse-api": { @@ -2038,10 +2038,10 @@ "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", "dev": true, "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" + "browserslist": "4.3.5", + "caniuse-lite": "1.0.30000913", + "lodash.memoize": "4.1.2", + "lodash.uniq": "4.5.0" } }, "caniuse-lite": { @@ -2068,10 +2068,10 @@ "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", "dev": true, "requires": { - "get-proxy": "^2.0.0", - "isurl": "^1.0.0-alpha5", - "tunnel-agent": "^0.6.0", - "url-to-options": "^1.0.1" + "get-proxy": "2.1.0", + "isurl": "1.0.0", + "tunnel-agent": "0.6.0", + "url-to-options": "1.0.1" } }, "center-align": { @@ -2080,8 +2080,8 @@ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" + "align-text": "0.1.4", + "lazy-cache": "1.0.4" } }, "chalk": { @@ -2090,9 +2090,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" } }, "chardet": { @@ -2107,19 +2107,19 @@ "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "fsevents": "1.2.4", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "lodash.debounce": "4.0.8", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1", + "upath": "1.1.0" }, "dependencies": { "anymatch": { @@ -2128,8 +2128,8 @@ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "micromatch": "3.1.10", + "normalize-path": "2.1.1" } }, "is-glob": { @@ -2138,7 +2138,7 @@ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "is-extglob": "2.1.1" } } } @@ -2155,10 +2155,10 @@ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" }, "dependencies": { "define-property": { @@ -2167,7 +2167,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } } } @@ -2178,7 +2178,7 @@ "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", "dev": true, "requires": { - "source-map": "~0.6.0" + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -2195,7 +2195,7 @@ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "restore-cursor": "2.0.0" } }, "cli-width": { @@ -2209,9 +2209,9 @@ "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==", "requires": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" + "good-listener": "1.2.2", + "select": "1.1.2", + "tiny-emitter": "2.0.2" } }, "cliui": { @@ -2220,8 +2220,8 @@ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", + "center-align": "0.1.3", + "right-align": "0.1.3", "wordwrap": "0.0.2" }, "dependencies": { @@ -2252,7 +2252,7 @@ "dev": true, "optional": true, "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "1.0.1" } }, "clone-stats": { @@ -2267,9 +2267,9 @@ "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", "dev": true, "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -2284,13 +2284,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -2299,7 +2299,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -2310,7 +2310,7 @@ "integrity": "sha512-5wfTTO8E2/ja4jFSxePXlG5nRu5bBtL/r1HCIpJW/lzT6yDtKl0u0Z4o/Vpz32IpKmBn7HerheEZQgA9N2DarQ==", "dev": true, "requires": { - "q": "^1.1.2" + "q": "1.5.1" } }, "collection-visit": { @@ -2319,8 +2319,8 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, "color": { @@ -2329,8 +2329,8 @@ "integrity": "sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg==", "dev": true, "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" + "color-convert": "1.9.3", + "color-string": "1.5.3" } }, "color-convert": { @@ -2354,8 +2354,8 @@ "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", "dev": true, "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" } }, "color-support": { @@ -2376,7 +2376,7 @@ "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", "dev": true, "requires": { - "lodash": "^4.5.0" + "lodash": "4.17.11" } }, "combined-stream": { @@ -2385,7 +2385,7 @@ "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "commander": { @@ -2394,7 +2394,7 @@ "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", "dev": true, "requires": { - "graceful-readlink": ">= 1.0.0" + "graceful-readlink": "1.0.1" } }, "component-bind": { @@ -2427,10 +2427,10 @@ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "buffer-from": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" }, "dependencies": { "isarray": { @@ -2445,13 +2445,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -2460,7 +2460,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -2471,7 +2471,7 @@ "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", "dev": true, "requires": { - "source-map": "^0.6.1" + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -2488,8 +2488,8 @@ "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", "dev": true, "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" + "ini": "1.3.5", + "proto-list": "1.2.4" } }, "connect": { @@ -2500,7 +2500,7 @@ "requires": { "debug": "2.6.9", "finalhandler": "1.1.0", - "parseurl": "~1.3.2", + "parseurl": "1.3.2", "utils-merge": "1.0.1" }, "dependencies": { @@ -2540,7 +2540,7 @@ "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", "dev": true, "requires": { - "bluebird": "^3.1.1" + "bluebird": "3.5.3" } }, "content-disposition": { @@ -2567,7 +2567,7 @@ "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", "dev": true, "requires": { - "safe-buffer": "~5.1.1" + "safe-buffer": "5.1.2" } }, "cookie": { @@ -2600,10 +2600,10 @@ "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", "dev": true, "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "parse-json": "^4.0.0" + "import-fresh": "2.0.0", + "is-directory": "0.3.1", + "js-yaml": "3.12.0", + "parse-json": "4.0.0" } }, "cross-spawn": { @@ -2612,11 +2612,11 @@ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "nice-try": "1.0.5", + "path-key": "2.0.1", + "semver": "5.6.0", + "shebang-command": "1.2.0", + "which": "1.3.1" } }, "css-color-names": { @@ -2631,8 +2631,8 @@ "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", "dev": true, "requires": { - "postcss": "^7.0.1", - "timsort": "^0.3.0" + "postcss": "7.0.6", + "timsort": "0.3.0" } }, "css-select": { @@ -2641,10 +2641,10 @@ "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==", "dev": true, "requires": { - "boolbase": "^1.0.0", - "css-what": "^2.1.2", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" + "boolbase": "1.0.0", + "css-what": "2.1.2", + "domutils": "1.7.0", + "nth-check": "1.0.2" } }, "css-select-base-adapter": { @@ -2659,8 +2659,8 @@ "integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==", "dev": true, "requires": { - "mdn-data": "~1.1.0", - "source-map": "^0.5.3" + "mdn-data": "1.1.4", + "source-map": "0.5.7" } }, "css-unit-converter": { @@ -2693,10 +2693,10 @@ "integrity": "sha512-AiXL90l+MDuQmRNyypG2P7ux7K4XklxYzNNUd5HXZCNcH8/N9bHPcpN97v8tXgRVeFL/Ed8iP8mVmAAu0ZpT7A==", "dev": true, "requires": { - "cosmiconfig": "^5.0.0", - "cssnano-preset-default": "^4.0.5", - "is-resolvable": "^1.0.0", - "postcss": "^7.0.0" + "cosmiconfig": "5.0.7", + "cssnano-preset-default": "4.0.5", + "is-resolvable": "1.1.0", + "postcss": "7.0.6" } }, "cssnano-preset-default": { @@ -2705,36 +2705,36 @@ "integrity": "sha512-f1uhya0ZAjPYtDD58QkBB0R+uYdzHPei7cDxJyQQIHt5acdhyGXaSXl2nDLzWHLwGFbZcHxQtkJS8mmNwnxTvw==", "dev": true, "requires": { - "css-declaration-sorter": "^4.0.1", - "cssnano-util-raw-cache": "^4.0.1", - "postcss": "^7.0.0", - "postcss-calc": "^7.0.0", - "postcss-colormin": "^4.0.2", - "postcss-convert-values": "^4.0.1", - "postcss-discard-comments": "^4.0.1", - "postcss-discard-duplicates": "^4.0.2", - "postcss-discard-empty": "^4.0.1", - "postcss-discard-overridden": "^4.0.1", - "postcss-merge-longhand": "^4.0.9", - "postcss-merge-rules": "^4.0.2", - "postcss-minify-font-values": "^4.0.2", - "postcss-minify-gradients": "^4.0.1", - "postcss-minify-params": "^4.0.1", - "postcss-minify-selectors": "^4.0.1", - "postcss-normalize-charset": "^4.0.1", - "postcss-normalize-display-values": "^4.0.1", - "postcss-normalize-positions": "^4.0.1", - "postcss-normalize-repeat-style": "^4.0.1", - "postcss-normalize-string": "^4.0.1", - "postcss-normalize-timing-functions": "^4.0.1", - "postcss-normalize-unicode": "^4.0.1", - "postcss-normalize-url": "^4.0.1", - "postcss-normalize-whitespace": "^4.0.1", - "postcss-ordered-values": "^4.1.1", - "postcss-reduce-initial": "^4.0.2", - "postcss-reduce-transforms": "^4.0.1", - "postcss-svgo": "^4.0.1", - "postcss-unique-selectors": "^4.0.1" + "css-declaration-sorter": "4.0.1", + "cssnano-util-raw-cache": "4.0.1", + "postcss": "7.0.6", + "postcss-calc": "7.0.1", + "postcss-colormin": "4.0.2", + "postcss-convert-values": "4.0.1", + "postcss-discard-comments": "4.0.1", + "postcss-discard-duplicates": "4.0.2", + "postcss-discard-empty": "4.0.1", + "postcss-discard-overridden": "4.0.1", + "postcss-merge-longhand": "4.0.9", + "postcss-merge-rules": "4.0.2", + "postcss-minify-font-values": "4.0.2", + "postcss-minify-gradients": "4.0.1", + "postcss-minify-params": "4.0.1", + "postcss-minify-selectors": "4.0.1", + "postcss-normalize-charset": "4.0.1", + "postcss-normalize-display-values": "4.0.1", + "postcss-normalize-positions": "4.0.1", + "postcss-normalize-repeat-style": "4.0.1", + "postcss-normalize-string": "4.0.1", + "postcss-normalize-timing-functions": "4.0.1", + "postcss-normalize-unicode": "4.0.1", + "postcss-normalize-url": "4.0.1", + "postcss-normalize-whitespace": "4.0.1", + "postcss-ordered-values": "4.1.1", + "postcss-reduce-initial": "4.0.2", + "postcss-reduce-transforms": "4.0.1", + "postcss-svgo": "4.0.1", + "postcss-unique-selectors": "4.0.1" } }, "cssnano-util-get-arguments": { @@ -2755,7 +2755,7 @@ "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", "dev": true, "requires": { - "postcss": "^7.0.0" + "postcss": "7.0.6" } }, "cssnano-util-same-parent": { @@ -2779,8 +2779,8 @@ "integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==", "dev": true, "requires": { - "mdn-data": "~1.1.0", - "source-map": "^0.5.3" + "mdn-data": "1.1.4", + "source-map": "0.5.7" } } } @@ -2791,7 +2791,7 @@ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "array-find-index": "^1.0.1" + "array-find-index": "1.0.2" } }, "custom-event": { @@ -2806,7 +2806,7 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "date-format": { @@ -2827,7 +2827,7 @@ "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "decamelize": { @@ -2848,14 +2848,14 @@ "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", "dev": true, "requires": { - "decompress-tar": "^4.0.0", - "decompress-tarbz2": "^4.0.0", - "decompress-targz": "^4.0.0", - "decompress-unzip": "^4.0.1", - "graceful-fs": "^4.1.10", - "make-dir": "^1.0.0", - "pify": "^2.3.0", - "strip-dirs": "^2.0.0" + "decompress-tar": "4.1.1", + "decompress-tarbz2": "4.1.1", + "decompress-targz": "4.1.1", + "decompress-unzip": "4.0.1", + "graceful-fs": "4.1.15", + "make-dir": "1.3.0", + "pify": "2.3.0", + "strip-dirs": "2.1.0" }, "dependencies": { "graceful-fs": { @@ -2878,7 +2878,7 @@ "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "1.0.1" } }, "decompress-tar": { @@ -2887,9 +2887,9 @@ "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", "dev": true, "requires": { - "file-type": "^5.2.0", - "is-stream": "^1.1.0", - "tar-stream": "^1.5.2" + "file-type": "5.2.0", + "is-stream": "1.1.0", + "tar-stream": "1.6.2" }, "dependencies": { "file-type": { @@ -2906,11 +2906,11 @@ "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", "dev": true, "requires": { - "decompress-tar": "^4.1.0", - "file-type": "^6.1.0", - "is-stream": "^1.1.0", - "seek-bzip": "^1.0.5", - "unbzip2-stream": "^1.0.9" + "decompress-tar": "4.1.1", + "file-type": "6.2.0", + "is-stream": "1.1.0", + "seek-bzip": "1.0.5", + "unbzip2-stream": "1.3.1" }, "dependencies": { "file-type": { @@ -2927,9 +2927,9 @@ "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", "dev": true, "requires": { - "decompress-tar": "^4.1.1", - "file-type": "^5.2.0", - "is-stream": "^1.1.0" + "decompress-tar": "4.1.1", + "file-type": "5.2.0", + "is-stream": "1.1.0" }, "dependencies": { "file-type": { @@ -2946,10 +2946,10 @@ "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", "dev": true, "requires": { - "file-type": "^3.8.0", - "get-stream": "^2.2.0", - "pify": "^2.3.0", - "yauzl": "^2.4.2" + "file-type": "3.9.0", + "get-stream": "2.3.1", + "pify": "2.3.0", + "yauzl": "2.10.0" }, "dependencies": { "file-type": { @@ -2964,8 +2964,8 @@ "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", "dev": true, "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" + "object-assign": "4.1.1", + "pinkie-promise": "2.0.1" } }, "object-assign": { @@ -2994,7 +2994,7 @@ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "^1.0.2" + "clone": "1.0.4" } }, "define-properties": { @@ -3003,7 +3003,7 @@ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { - "object-keys": "^1.0.12" + "object-keys": "1.0.12" } }, "define-property": { @@ -3012,8 +3012,8 @@ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "is-descriptor": "1.0.2", + "isobject": "3.0.1" }, "dependencies": { "is-accessor-descriptor": { @@ -3022,7 +3022,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -3031,7 +3031,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -3040,9 +3040,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -3099,8 +3099,8 @@ "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", "dev": true, "requires": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" + "arrify": "1.0.1", + "path-type": "3.0.0" } }, "doctrine": { @@ -3109,7 +3109,7 @@ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "^2.0.2" + "esutils": "2.0.2" } }, "dom-serialize": { @@ -3118,10 +3118,10 @@ "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", "dev": true, "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" + "custom-event": "1.0.1", + "ent": "2.2.0", + "extend": "3.0.2", + "void-elements": "2.0.1" } }, "dom-serializer": { @@ -3130,8 +3130,8 @@ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", "dev": true, "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" + "domelementtype": "1.1.3", + "entities": "1.1.2" }, "dependencies": { "domelementtype": { @@ -3154,8 +3154,8 @@ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", "dev": true, "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "dom-serializer": "0.1.0", + "domelementtype": "1.2.1" } }, "dot-prop": { @@ -3164,7 +3164,7 @@ "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "dev": true, "requires": { - "is-obj": "^1.0.0" + "is-obj": "1.0.1" } }, "download": { @@ -3174,17 +3174,17 @@ "dev": true, "optional": true, "requires": { - "caw": "^2.0.0", - "content-disposition": "^0.5.2", - "decompress": "^4.0.0", - "ext-name": "^5.0.0", + "caw": "2.0.1", + "content-disposition": "0.5.2", + "decompress": "4.2.0", + "ext-name": "5.0.0", "file-type": "5.2.0", - "filenamify": "^2.0.0", - "get-stream": "^3.0.0", - "got": "^7.0.0", - "make-dir": "^1.0.0", - "p-event": "^1.0.0", - "pify": "^3.0.0" + "filenamify": "2.1.0", + "get-stream": "3.0.0", + "got": "7.1.0", + "make-dir": "1.3.0", + "p-event": "1.3.0", + "pify": "3.0.0" }, "dependencies": { "file-type": { @@ -3208,7 +3208,7 @@ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "~1.1.9" + "readable-stream": "1.1.14" } }, "duplexer3": { @@ -3223,8 +3223,8 @@ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" } }, "ee-first": { @@ -3251,7 +3251,7 @@ "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", "dev": true, "requires": { - "once": "~1.3.0" + "once": "1.3.3" } }, "engine.io": { @@ -3260,12 +3260,12 @@ "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { - "accepts": "~1.3.4", + "accepts": "1.3.5", "base64id": "1.0.0", "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" + "debug": "3.1.0", + "engine.io-parser": "2.1.3", + "ws": "3.3.3" }, "dependencies": { "debug": { @@ -3293,14 +3293,14 @@ "requires": { "component-emitter": "1.2.1", "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", + "debug": "3.1.0", + "engine.io-parser": "2.1.3", "has-cors": "1.1.0", "indexof": "0.0.1", "parseqs": "0.0.5", "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", + "ws": "3.3.3", + "xmlhttprequest-ssl": "1.5.5", "yeast": "0.1.2" }, "dependencies": { @@ -3328,10 +3328,10 @@ "dev": true, "requires": { "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", + "arraybuffer.slice": "0.0.7", "base64-arraybuffer": "0.1.5", "blob": "0.0.5", - "has-binary2": "~1.0.2" + "has-binary2": "1.0.3" } }, "ent": { @@ -3353,7 +3353,7 @@ "dev": true, "optional": true, "requires": { - "prr": "~1.0.1" + "prr": "1.0.1" } }, "error": { @@ -3362,8 +3362,8 @@ "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", "dev": true, "requires": { - "string-template": "~0.2.1", - "xtend": "~4.0.0" + "string-template": "0.2.1", + "xtend": "4.0.1" } }, "error-ex": { @@ -3372,7 +3372,7 @@ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "is-arrayish": "0.2.1" } }, "es-abstract": { @@ -3381,11 +3381,11 @@ "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", "dev": true, "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" + "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" } }, "es-to-primitive": { @@ -3394,9 +3394,9 @@ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "dev": true, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "1.1.4", + "is-date-object": "1.0.1", + "is-symbol": "1.0.2" } }, "es6-promise": { @@ -3423,11 +3423,11 @@ "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", "dev": true, "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.6.1" }, "dependencies": { "esprima": { @@ -3451,44 +3451,44 @@ "integrity": "sha512-g4KWpPdqN0nth+goDNICNXGfJF7nNnepthp46CAlJoJtC5K/cLu3NgCM3AHu1CkJ5Hzt9V0Y0PBAO6Ay/gGb+w==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.5.3", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^2.1.0", - "eslint-scope": "^4.0.0", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^4.0.0", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", - "ignore": "^4.0.6", - "imurmurhash": "^0.1.4", - "inquirer": "^6.1.0", - "is-resolvable": "^1.1.0", - "js-yaml": "^3.12.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.5", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^5.0.2", - "text-table": "^0.2.0" + "@babel/code-frame": "7.0.0", + "ajv": "6.6.1", + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "4.1.0", + "doctrine": "2.1.0", + "eslint-scope": "4.0.0", + "eslint-utils": "1.3.1", + "eslint-visitor-keys": "1.0.0", + "espree": "4.1.0", + "esquery": "1.0.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.3", + "globals": "11.9.0", + "ignore": "4.0.6", + "imurmurhash": "0.1.4", + "inquirer": "6.2.1", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.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", + "pluralize": "7.0.0", + "progress": "2.0.1", + "regexpp": "2.0.1", + "require-uncached": "1.0.3", + "semver": "5.6.0", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "5.1.1", + "text-table": "0.2.0" }, "dependencies": { "ansi-regex": { @@ -3503,12 +3503,12 @@ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": 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" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" } }, "minimatch": { @@ -3517,7 +3517,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "strip-ansi": { @@ -3526,7 +3526,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -3537,8 +3537,8 @@ "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "esrecurse": "4.2.1", + "estraverse": "4.2.0" } }, "eslint-utils": { @@ -3559,9 +3559,9 @@ "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", "dev": true, "requires": { - "acorn": "^6.0.2", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" + "acorn": "6.0.4", + "acorn-jsx": "5.0.1", + "eslint-visitor-keys": "1.0.0" } }, "esprima": { @@ -3576,7 +3576,7 @@ "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "4.2.0" } }, "esrecurse": { @@ -3585,7 +3585,7 @@ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "^4.1.0" + "estraverse": "4.2.0" } }, "estemplate": { @@ -3594,8 +3594,8 @@ "integrity": "sha1-FxSp1GGQc4rJWLyv1J4CnNpWo54=", "dev": true, "requires": { - "esprima": "^2.7.2", - "estraverse": "^4.1.1" + "esprima": "2.7.3", + "estraverse": "4.2.0" }, "dependencies": { "esprima": { @@ -3630,13 +3630,13 @@ "integrity": "sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g==", "dev": true, "requires": { - "duplexer": "^0.1.1", - "from": "^0.1.7", + "duplexer": "0.1.1", + "from": "0.1.7", "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" + "pause-stream": "0.0.11", + "split": "1.0.1", + "stream-combiner": "0.2.2", + "through": "2.3.8" } }, "eventemitter3": { @@ -3652,11 +3652,11 @@ "dev": true, "optional": true, "requires": { - "execa": "^0.7.0", - "p-finally": "^1.0.0", - "pify": "^3.0.0", - "rimraf": "^2.5.4", - "tempfile": "^2.0.0" + "execa": "0.7.0", + "p-finally": "1.0.0", + "pify": "3.0.0", + "rimraf": "2.6.2", + "tempfile": "2.0.0" } }, "execa": { @@ -3665,13 +3665,13 @@ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.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" + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" }, "dependencies": { "cross-spawn": { @@ -3680,9 +3680,9 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "lru-cache": "4.1.5", + "shebang-command": "1.2.0", + "which": "1.3.1" } }, "lru-cache": { @@ -3691,8 +3691,8 @@ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } } } @@ -3704,7 +3704,7 @@ "dev": true, "optional": true, "requires": { - "pify": "^2.2.0" + "pify": "2.3.0" }, "dependencies": { "pify": { @@ -3722,9 +3722,9 @@ "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" + "array-slice": "0.2.3", + "array-unique": "0.2.1", + "braces": "0.1.5" }, "dependencies": { "array-slice": { @@ -3745,7 +3745,7 @@ "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", "dev": true, "requires": { - "expand-range": "^0.1.0" + "expand-range": "0.1.1" } }, "expand-range": { @@ -3754,8 +3754,8 @@ "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" + "is-number": "0.1.1", + "repeat-string": "0.2.2" } }, "is-number": { @@ -3778,13 +3778,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "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" + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "debug": { @@ -3802,7 +3802,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -3811,7 +3811,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "ms": { @@ -3828,7 +3828,7 @@ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "^2.1.0" + "fill-range": "2.2.4" }, "dependencies": { "fill-range": { @@ -3837,11 +3837,11 @@ "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true, "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.1.1", + "repeat-element": "1.1.3", + "repeat-string": "1.6.1" } }, "is-number": { @@ -3850,7 +3850,7 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" } }, "isarray": { @@ -3874,7 +3874,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -3885,7 +3885,7 @@ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "^1.0.1" + "homedir-polyfill": "1.0.1" } }, "ext-list": { @@ -3894,7 +3894,7 @@ "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", "dev": true, "requires": { - "mime-db": "^1.28.0" + "mime-db": "1.37.0" } }, "ext-name": { @@ -3903,8 +3903,8 @@ "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", "dev": true, "requires": { - "ext-list": "^2.0.0", - "sort-keys-length": "^1.0.0" + "ext-list": "2.2.2", + "sort-keys-length": "1.0.1" } }, "extend": { @@ -3919,8 +3919,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -3929,7 +3929,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -3940,9 +3940,9 @@ "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", "dev": true, "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "chardet": "0.7.0", + "iconv-lite": "0.4.24", + "tmp": "0.0.33" } }, "extglob": { @@ -3951,14 +3951,14 @@ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "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" + "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.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -3967,7 +3967,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "extend-shallow": { @@ -3976,7 +3976,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "is-accessor-descriptor": { @@ -3985,7 +3985,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -3994,7 +3994,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -4003,9 +4003,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -4037,7 +4037,7 @@ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "dev": true, "requires": { - "pend": "~1.2.0" + "pend": "1.2.0" } }, "ms": { @@ -4052,7 +4052,7 @@ "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", "dev": true, "requires": { - "fd-slicer": "~1.0.1" + "fd-slicer": "1.0.1" } } } @@ -4069,10 +4069,10 @@ "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", "dev": true, "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "parse-node-version": "1.0.0", + "time-stamp": "1.1.0" } }, "fast-deep-equal": { @@ -4087,12 +4087,12 @@ "integrity": "sha512-FjK2nCGI/McyzgNtTESqaWP3trPvHyRyoyY70hxjc3oKPNmDe8taohLZpoVKoUjW85tbU5txaYUZCNtVzygl1g==", "dev": true, "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" + "@mrmlnc/readdir-enhanced": "2.2.1", + "@nodelib/fs.stat": "1.1.3", + "glob-parent": "3.1.0", + "is-glob": "4.0.0", + "merge2": "1.2.3", + "micromatch": "3.1.10" }, "dependencies": { "is-glob": { @@ -4101,7 +4101,7 @@ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "is-extglob": "2.1.1" } } } @@ -4124,7 +4124,7 @@ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "websocket-driver": ">=0.5.1" + "websocket-driver": "0.7.0" } }, "fd-slicer": { @@ -4133,7 +4133,7 @@ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "dev": true, "requires": { - "pend": "~1.2.0" + "pend": "1.2.0" } }, "figures": { @@ -4142,7 +4142,7 @@ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5" + "escape-string-regexp": "1.0.5" } }, "file-entry-cache": { @@ -4151,8 +4151,8 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "1.3.4", + "object-assign": "4.1.1" }, "dependencies": { "object-assign": { @@ -4187,9 +4187,9 @@ "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", "dev": true, "requires": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.0", - "trim-repeated": "^1.0.0" + "filename-reserved-regex": "2.0.0", + "strip-outer": "1.0.1", + "trim-repeated": "1.0.0" } }, "fill-range": { @@ -4198,10 +4198,10 @@ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" }, "dependencies": { "extend-shallow": { @@ -4210,7 +4210,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -4222,12 +4222,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.0" + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" }, "dependencies": { "debug": { @@ -4259,8 +4259,8 @@ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" } }, "find-versions": { @@ -4270,8 +4270,8 @@ "dev": true, "optional": true, "requires": { - "array-uniq": "^2.0.0", - "semver-regex": "^2.0.0" + "array-uniq": "2.0.0", + "semver-regex": "2.0.0" }, "dependencies": { "array-uniq": { @@ -4289,10 +4289,10 @@ "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "dev": true, "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.10", + "resolve-dir": "1.0.1" } }, "fined": { @@ -4301,11 +4301,11 @@ "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.2" } }, "first-chunk-stream": { @@ -4326,10 +4326,10 @@ "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", "dev": true, "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" + "circular-json": "0.3.3", + "graceful-fs": "4.1.15", + "rimraf": "2.6.2", + "write": "0.2.1" }, "dependencies": { "graceful-fs": { @@ -4351,7 +4351,7 @@ "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", "dev": true, "requires": { - "debug": "=3.1.0" + "debug": "3.1.0" }, "dependencies": { "debug": { @@ -4388,7 +4388,7 @@ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { - "for-in": "^1.0.1" + "for-in": "1.0.2" } }, "forever-agent": { @@ -4403,9 +4403,9 @@ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "asynckit": "0.4.0", + "combined-stream": "1.0.7", + "mime-types": "2.1.21" } }, "fragment-cache": { @@ -4414,7 +4414,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "^0.2.2" + "map-cache": "0.2.2" } }, "fresh": { @@ -4436,8 +4436,8 @@ "dev": true, "optional": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" + "inherits": "2.0.3", + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -4454,13 +4454,13 @@ "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -4470,7 +4470,7 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -4487,9 +4487,9 @@ "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" + "graceful-fs": "4.1.15", + "jsonfile": "2.4.0", + "klaw": "1.3.1" }, "dependencies": { "graceful-fs": { @@ -4506,7 +4506,7 @@ "integrity": "sha1-gAI4I5gfn//+AWCei+Zo9prknnA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2" + "graceful-fs": "4.1.15" }, "dependencies": { "graceful-fs": { @@ -4530,8 +4530,8 @@ "dev": true, "optional": true, "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" + "nan": "2.11.1", + "node-pre-gyp": "0.10.0" }, "dependencies": { "abbrev": { @@ -5089,7 +5089,7 @@ "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", "dev": true, "requires": { - "globule": "~0.1.0" + "globule": "0.1.0" } }, "get-proxy": { @@ -5098,7 +5098,7 @@ "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", "dev": true, "requires": { - "npm-conf": "^1.1.0" + "npm-conf": "1.1.3" } }, "get-stdin": { @@ -5125,7 +5125,7 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "gifsicle": { @@ -5135,10 +5135,10 @@ "dev": true, "optional": true, "requires": { - "bin-build": "^3.0.0", - "bin-wrapper": "^4.0.0", - "execa": "^1.0.0", - "logalot": "^2.0.0" + "bin-build": "3.0.0", + "bin-wrapper": "4.1.0", + "execa": "1.0.0", + "logalot": "2.1.0" }, "dependencies": { "execa": { @@ -5148,13 +5148,13 @@ "dev": true, "optional": true, "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" + "cross-spawn": "6.0.5", + "get-stream": "4.1.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" } }, "get-stream": { @@ -5164,7 +5164,7 @@ "dev": true, "optional": true, "requires": { - "pump": "^3.0.0" + "pump": "3.0.0" } } } @@ -5175,10 +5175,10 @@ "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.3.3" } }, "glob-base": { @@ -5187,8 +5187,8 @@ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" + "glob-parent": "2.0.0", + "is-glob": "2.0.1" }, "dependencies": { "glob-parent": { @@ -5197,7 +5197,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "^2.0.0" + "is-glob": "2.0.1" } }, "is-extglob": { @@ -5212,7 +5212,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } } } @@ -5223,8 +5223,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "is-glob": "3.1.0", + "path-dirname": "1.0.2" } }, "glob-stream": { @@ -5233,12 +5233,12 @@ "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", "dev": true, "requires": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" }, "dependencies": { "readable-stream": { @@ -5247,10 +5247,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "through2": { @@ -5259,8 +5259,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } } } @@ -5277,7 +5277,7 @@ "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", "dev": true, "requires": { - "gaze": "^0.5.1" + "gaze": "0.5.2" } }, "glob2base": { @@ -5286,7 +5286,7 @@ "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", "dev": true, "requires": { - "find-index": "^0.1.1" + "find-index": "0.1.1" } }, "global-modules": { @@ -5295,9 +5295,9 @@ "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" } }, "global-prefix": { @@ -5306,11 +5306,11 @@ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.1" } }, "globals": { @@ -5325,13 +5325,13 @@ "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", "dev": true, "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "fast-glob": "2.2.4", + "glob": "7.1.3", + "ignore": "3.3.10", + "pify": "3.0.0", + "slash": "1.0.0" }, "dependencies": { "glob": { @@ -5340,12 +5340,12 @@ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": 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" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" } }, "ignore": { @@ -5360,7 +5360,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } } } @@ -5371,9 +5371,9 @@ "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" }, "dependencies": { "glob": { @@ -5382,9 +5382,9 @@ "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", "dev": true, "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" } }, "graceful-fs": { @@ -5411,8 +5411,8 @@ "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", "dev": true, "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" + "lru-cache": "2.7.3", + "sigmund": "1.0.1" } } } @@ -5423,7 +5423,7 @@ "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", "dev": true, "requires": { - "sparkles": "^1.0.0" + "sparkles": "1.0.1" } }, "good-listener": { @@ -5431,7 +5431,7 @@ "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", "requires": { - "delegate": "^3.1.2" + "delegate": "3.2.0" } }, "got": { @@ -5441,20 +5441,20 @@ "dev": true, "optional": true, "requires": { - "decompress-response": "^3.2.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-plain-obj": "^1.1.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "p-cancelable": "^0.3.0", - "p-timeout": "^1.1.1", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "url-parse-lax": "^1.0.0", - "url-to-options": "^1.0.1" + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" } }, "graceful-fs": { @@ -5463,7 +5463,7 @@ "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", "dev": true, "requires": { - "natives": "^1.1.0" + "natives": "1.1.6" } }, "graceful-readlink": { @@ -5478,19 +5478,19 @@ "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", "dev": true, "requires": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.1.0", + "liftoff": "2.5.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" }, "dependencies": { "ansi-styles": { @@ -5505,11 +5505,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "semver": { @@ -5532,10 +5532,10 @@ "integrity": "sha512-oomaIqDXxFkg7lbpBou/gnUkX51/Y/M2ZfSjL2hdqXTAlSWZcgZtd2o0cOH0r/eE8LWD0+Q/PsLsr2DKOoqToQ==", "dev": true, "requires": { - "plugin-error": "^1.0.1", - "replace-ext": "^1.0.0", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" + "plugin-error": "1.0.1", + "replace-ext": "1.0.0", + "through2": "2.0.5", + "vinyl-sourcemaps-apply": "0.2.1" }, "dependencies": { "replace-ext": { @@ -5564,9 +5564,9 @@ "integrity": "sha512-9E1oLoOWfhSXHGv6QlwXJim7uNzd9EVlWK+21tCU9Ju/kR0/p2AZYPz4qSchgO8PlLIH4FpZYfzwS+rEksZjIg==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "inherits": "2.0.3", + "string_decoder": "1.2.0", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -5575,7 +5575,7 @@ "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "through2": { @@ -5584,8 +5584,8 @@ "integrity": "sha512-8B+sevlqP4OiCjonI1Zw03Sf8PuV1eRsYQgLad5eonILOdyeRsY27A/2Ze8IlvlMvq31OH+3fz/styI7Ya62yQ==", "dev": true, "requires": { - "readable-stream": "2 || 3", - "xtend": "~4.0.1" + "readable-stream": "3.0.6", + "xtend": "4.0.1" } } } @@ -5596,9 +5596,9 @@ "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", "dev": true, "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" + "concat-with-sourcemaps": "1.1.0", + "through2": "2.0.5", + "vinyl": "2.2.0" }, "dependencies": { "clone": { @@ -5625,12 +5625,12 @@ "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", "dev": true, "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "clone": "2.1.2", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" } } } @@ -5641,15 +5641,15 @@ "integrity": "sha512-FknHeA6smZhiRNrK/3UVH8BHLCFHS7WZdE7Y2VbZHtxye1UTIa5ZY0Cnst6O9n3kL8z7y43QI+acx3nUtJoiHw==", "dev": true, "requires": { - "ansi-colors": "^2.0.5", - "connect": "^3.6.6", - "connect-livereload": "^0.6.0", - "event-stream": "^3.3.4", - "fancy-log": "^1.3.2", - "send": "^0.16.2", - "serve-index": "^1.9.1", - "serve-static": "^1.13.2", - "tiny-lr": "^1.1.1" + "ansi-colors": "2.0.5", + "connect": "3.6.6", + "connect-livereload": "0.6.0", + "event-stream": "3.3.5", + "fancy-log": "1.3.3", + "send": "0.16.2", + "serve-index": "1.9.1", + "serve-static": "1.13.2", + "tiny-lr": "1.1.1" }, "dependencies": { "ansi-colors": { @@ -5666,9 +5666,9 @@ "integrity": "sha512-9GUqCqh85C7rP9120cpxXuZz2ayq3BZc85pCTuPJS03VQYxne0aWPIXWx6LSvsGPa3uRqtSO537vaugOh+5cXg==", "dev": true, "requires": { - "eslint": "^5.0.1", - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.1" + "eslint": "5.9.0", + "fancy-log": "1.3.3", + "plugin-error": "1.0.1" } }, "gulp-imagemin": { @@ -5677,17 +5677,17 @@ "integrity": "sha512-bKJMix4r6EQPVV2u8sUglw6Rn0PSp6i70pSK2ECN7j0dRy0w/Lz5SBbynY3MfGBZ0cTMZlaUq+6LyKlZgP74Ew==", "dev": true, "requires": { - "chalk": "^2.4.1", - "fancy-log": "^1.3.2", - "imagemin": "^6.0.0", - "imagemin-gifsicle": "^6.0.1", - "imagemin-jpegtran": "^6.0.0", - "imagemin-optipng": "^6.0.0", - "imagemin-svgo": "^7.0.0", - "plugin-error": "^1.0.1", - "plur": "^3.0.1", - "pretty-bytes": "^5.1.0", - "through2-concurrent": "^2.0.0" + "chalk": "2.4.1", + "fancy-log": "1.3.3", + "imagemin": "6.0.0", + "imagemin-gifsicle": "6.0.1", + "imagemin-jpegtran": "6.0.0", + "imagemin-optipng": "6.0.0", + "imagemin-svgo": "7.0.0", + "plugin-error": "1.0.1", + "plur": "3.0.1", + "pretty-bytes": "5.1.0", + "through2-concurrent": "2.0.0" } }, "gulp-less": { @@ -5696,13 +5696,13 @@ "integrity": "sha512-hmM2k0FfQp7Ptm3ZaqO2CkMX3hqpiIOn4OHtuSsCeFym63F7oWlEua5v6u1cIjVUKYsVIs9zPg9vbqTEb/udpA==", "dev": true, "requires": { - "accord": "^0.29.0", - "less": "2.6.x || ^3.7.1", - "object-assign": "^4.0.1", - "plugin-error": "^0.1.2", - "replace-ext": "^1.0.0", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" + "accord": "0.29.0", + "less": "3.9.0", + "object-assign": "4.1.1", + "plugin-error": "0.1.2", + "replace-ext": "1.0.0", + "through2": "2.0.5", + "vinyl-sourcemaps-apply": "0.2.1" }, "dependencies": { "arr-diff": { @@ -5711,8 +5711,8 @@ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" } }, "arr-union": { @@ -5733,7 +5733,7 @@ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "dev": true, "requires": { - "kind-of": "^1.1.0" + "kind-of": "1.1.0" } }, "kind-of": { @@ -5754,11 +5754,11 @@ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" } }, "replace-ext": { @@ -5775,8 +5775,8 @@ "integrity": "sha1-J7Z6Ql6zh1ImNFq4lgTXN/Y1fCE=", "dev": true, "requires": { - "angular": "~1.3.1", - "angular-animate": "~1.3.1", + "angular": "1.3.20", + "angular-animate": "1.3.20", "canonical-path": "0.0.2", "extend": "1.3.0", "gulp-util": "3.0.0", @@ -5818,11 +5818,11 @@ "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", "dev": true, "requires": { - "ansi-styles": "^1.1.0", - "escape-string-regexp": "^1.0.0", - "has-ansi": "^0.1.0", - "strip-ansi": "^0.3.0", - "supports-color": "^0.2.0" + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" } }, "clone": { @@ -5837,8 +5837,8 @@ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", "dev": true, "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" + "get-stdin": "4.0.1", + "meow": "3.7.0" } }, "extend": { @@ -5853,15 +5853,15 @@ "integrity": "sha1-b+7cR9aXKCO6zplH/F9GvYo0Zuc=", "dev": true, "requires": { - "chalk": "^0.5.0", - "dateformat": "^1.0.7-1.2.3", - "lodash": "^2.4.1", - "lodash._reinterpolate": "^2.4.1", - "lodash.template": "^2.4.1", - "minimist": "^0.2.0", - "multipipe": "^0.1.0", - "through2": "^0.5.0", - "vinyl": "^0.2.1" + "chalk": "0.5.1", + "dateformat": "1.0.12", + "lodash": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.template": "2.4.1", + "minimist": "0.2.0", + "multipipe": "0.1.2", + "through2": "0.5.1", + "vinyl": "0.2.3" }, "dependencies": { "through2": { @@ -5870,8 +5870,8 @@ "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", "dev": true, "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" + "readable-stream": "1.0.34", + "xtend": "3.0.0" } } } @@ -5882,7 +5882,7 @@ "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", "dev": true, "requires": { - "ansi-regex": "^0.2.0" + "ansi-regex": "0.2.1" } }, "lodash": { @@ -5903,8 +5903,8 @@ "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._objecttypes": "2.4.1", + "lodash.keys": "2.4.1" } }, "lodash.escape": { @@ -5913,9 +5913,9 @@ "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", "dev": true, "requires": { - "lodash._escapehtmlchar": "~2.4.1", - "lodash._reunescapedhtml": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._escapehtmlchar": "2.4.1", + "lodash._reunescapedhtml": "2.4.1", + "lodash.keys": "2.4.1" } }, "lodash.keys": { @@ -5924,9 +5924,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" } }, "lodash.template": { @@ -5935,13 +5935,13 @@ "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", "dev": true, "requires": { - "lodash._escapestringchar": "~2.4.1", - "lodash._reinterpolate": "~2.4.1", - "lodash.defaults": "~2.4.1", - "lodash.escape": "~2.4.1", - "lodash.keys": "~2.4.1", - "lodash.templatesettings": "~2.4.1", - "lodash.values": "~2.4.1" + "lodash._escapestringchar": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.defaults": "2.4.1", + "lodash.escape": "2.4.1", + "lodash.keys": "2.4.1", + "lodash.templatesettings": "2.4.1", + "lodash.values": "2.4.1" } }, "lodash.templatesettings": { @@ -5950,8 +5950,8 @@ "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", "dev": true, "requires": { - "lodash._reinterpolate": "~2.4.1", - "lodash.escape": "~2.4.1" + "lodash._reinterpolate": "2.4.1", + "lodash.escape": "2.4.1" } }, "merge-stream": { @@ -5960,7 +5960,7 @@ "integrity": "sha1-5oIPet267gA/SMpKWMfFolPV4Fw=", "dev": true, "requires": { - "through2": "^0.5.1" + "through2": "0.5.1" }, "dependencies": { "through2": { @@ -5969,8 +5969,8 @@ "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", "dev": true, "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" + "readable-stream": "1.0.34", + "xtend": "3.0.0" } } } @@ -5987,10 +5987,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "strip-ansi": { @@ -5999,7 +5999,7 @@ "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", "dev": true, "requires": { - "ansi-regex": "^0.2.1" + "ansi-regex": "0.2.1" } }, "supports-color": { @@ -6014,8 +6014,8 @@ "integrity": "sha1-90KzKJPovSYUbnieT9LMssB6cX4=", "dev": true, "requires": { - "readable-stream": ">=1.0.27-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" }, "dependencies": { "xtend": { @@ -6032,7 +6032,7 @@ "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", "dev": true, "requires": { - "clone-stats": "~0.0.1" + "clone-stats": "0.0.1" } }, "vinyl-fs": { @@ -6041,14 +6041,14 @@ "integrity": "sha1-LiXP5t9cgIGPl/9Be/XCGkHkpJs=", "dev": true, "requires": { - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "lodash": "^2.4.1", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "lodash": "2.4.1", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.1", + "vinyl": "0.4.6" }, "dependencies": { "vinyl": { @@ -6057,8 +6057,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "0.2.0", + "clone-stats": "0.0.1" } } } @@ -6077,10 +6077,10 @@ "integrity": "sha512-dohokw+npnt48AsD0hhvCLEHLnDMqM35F+amvIfJlX1H2nNHYUClR0Oy1rI0TvbL1/pHiHGNLmohhk+kvwIKjA==", "dev": true, "requires": { - "colors": "^1.1.2", + "colors": "1.1.2", "opn": "5.2.0", - "plugin-log": "^0.1.0", - "through2": "^2.0.1" + "plugin-log": "0.1.0", + "through2": "2.0.5" } }, "gulp-postcss": { @@ -6089,11 +6089,11 @@ "integrity": "sha512-Wtl6vH7a+8IS/fU5W9IbOpcaLqKxd5L1DUOzaPmlnCbX1CrG0aWdwVnC3Spn8th0m8D59YbysV5zPUe1n/GJYg==", "dev": true, "requires": { - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.1", - "postcss": "^7.0.2", - "postcss-load-config": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.1" + "fancy-log": "1.3.3", + "plugin-error": "1.0.1", + "postcss": "7.0.6", + "postcss-load-config": "2.0.0", + "vinyl-sourcemaps-apply": "0.2.1" } }, "gulp-rename": { @@ -6108,7 +6108,7 @@ "integrity": "sha1-xnYqLx8N4KP8WVohWZ0/rI26Gso=", "dev": true, "requires": { - "through2": "^2.0.1" + "through2": "2.0.5" } }, "gulp-util": { @@ -6117,24 +6117,24 @@ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.3", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" + "through2": "2.0.5", + "vinyl": "0.5.3" }, "dependencies": { "ansi-styles": { @@ -6149,11 +6149,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "supports-color": { @@ -6171,17 +6171,17 @@ "dev": true, "requires": { "ansi-colors": "1.1.0", - "anymatch": "^1.3.0", - "chokidar": "^2.0.0", + "anymatch": "1.3.2", + "chokidar": "2.0.4", "fancy-log": "1.3.2", - "glob-parent": "^3.0.1", - "object-assign": "^4.1.0", - "path-is-absolute": "^1.0.1", + "glob-parent": "3.1.0", + "object-assign": "4.1.1", + "path-is-absolute": "1.0.1", "plugin-error": "1.0.1", - "readable-stream": "^2.2.2", - "slash": "^1.0.0", - "vinyl": "^2.1.0", - "vinyl-file": "^2.0.0" + "readable-stream": "2.3.6", + "slash": "1.0.0", + "vinyl": "2.2.0", + "vinyl-file": "2.0.0" }, "dependencies": { "clone": { @@ -6202,9 +6202,9 @@ "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "time-stamp": "^1.0.0" + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" } }, "isarray": { @@ -6225,13 +6225,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "replace-ext": { @@ -6246,7 +6246,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "vinyl": { @@ -6255,12 +6255,12 @@ "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", "dev": true, "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "clone": "2.1.2", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" } } } @@ -6271,16 +6271,16 @@ "integrity": "sha1-FaXCBI4nIecFOaYbrxw0oLxfJyk=", "dev": true, "requires": { - "consolidate": "^0.14.1", - "es6-promise": "^3.1.2", - "fs-readfile-promise": "^2.0.1", - "js-yaml": "^3.2.6", - "lodash": "^4.11.1", - "node.extend": "^1.1.2", - "plugin-error": "^0.1.2", - "through2": "^2.0.1", - "tryit": "^1.0.1", - "vinyl-bufferstream": "^1.0.1" + "consolidate": "0.14.5", + "es6-promise": "3.3.1", + "fs-readfile-promise": "2.0.1", + "js-yaml": "3.12.0", + "lodash": "4.17.11", + "node.extend": "1.1.8", + "plugin-error": "0.1.2", + "through2": "2.0.5", + "tryit": "1.0.3", + "vinyl-bufferstream": "1.0.1" }, "dependencies": { "arr-diff": { @@ -6289,8 +6289,8 @@ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" } }, "arr-union": { @@ -6311,7 +6311,7 @@ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "dev": true, "requires": { - "kind-of": "^1.1.0" + "kind-of": "1.1.0" } }, "kind-of": { @@ -6326,11 +6326,11 @@ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" } } } @@ -6341,12 +6341,12 @@ "integrity": "sha1-3uYqpISqupVHqT0f9c0MPQvtwDE=", "dev": true, "requires": { - "escodegen": "^1.6.1", - "esprima": "^2.3.0", - "estemplate": "*", - "gulp-util": "~3.0.5", - "through2": "*", - "vinyl-sourcemaps-apply": "^0.1.4" + "escodegen": "1.11.0", + "esprima": "2.7.3", + "estemplate": "0.5.1", + "gulp-util": "3.0.8", + "through2": "2.0.5", + "vinyl-sourcemaps-apply": "0.1.4" }, "dependencies": { "esprima": { @@ -6361,7 +6361,7 @@ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "requires": { - "amdefine": ">=0.0.4" + "amdefine": "1.0.1" } }, "vinyl-sourcemaps-apply": { @@ -6370,7 +6370,7 @@ "integrity": "sha1-xfy9Q+LyOEI8LcmL3db3m3K8NFs=", "dev": true, "requires": { - "source-map": "^0.1.39" + "source-map": "0.1.43" } } } @@ -6381,7 +6381,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "^1.0.0" + "glogg": "1.0.1" } }, "har-schema": { @@ -6396,8 +6396,8 @@ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "dev": true, "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" + "ajv": "6.6.1", + "har-schema": "2.0.0" } }, "has": { @@ -6406,7 +6406,7 @@ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "^1.1.1" + "function-bind": "1.1.1" } }, "has-ansi": { @@ -6415,7 +6415,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "has-binary2": { @@ -6453,7 +6453,7 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "^1.0.0" + "sparkles": "1.0.1" } }, "has-symbol-support-x": { @@ -6474,7 +6474,7 @@ "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", "dev": true, "requires": { - "has-symbol-support-x": "^1.4.1" + "has-symbol-support-x": "1.4.2" } }, "has-value": { @@ -6483,9 +6483,9 @@ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" } }, "has-values": { @@ -6494,8 +6494,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-number": "3.0.0", + "kind-of": "4.0.0" }, "dependencies": { "kind-of": { @@ -6504,7 +6504,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -6515,8 +6515,8 @@ "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", "dev": true, "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" + "is-stream": "1.1.0", + "pinkie-promise": "2.0.1" } }, "hex-color-regex": { @@ -6531,7 +6531,7 @@ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "^1.0.0" + "parse-passwd": "1.0.0" } }, "hosted-git-info": { @@ -6571,10 +6571,10 @@ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "depd": "~1.1.2", + "depd": "1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "statuses": "1.5.0" }, "dependencies": { "statuses": { @@ -6597,9 +6597,9 @@ "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", "dev": true, "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" + "eventemitter3": "3.1.0", + "follow-redirects": "1.5.10", + "requires-port": "1.0.0" } }, "http-signature": { @@ -6608,9 +6608,9 @@ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.15.2" } }, "iconv-lite": { @@ -6619,7 +6619,7 @@ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } }, "ieee754": { @@ -6647,12 +6647,12 @@ "integrity": "sha512-m4Mxwt2QvCp1F85HXoTungXk0Y6XzuvQGqrK9qEddQfo/7x4aZjRENmyXXfc29ei4Mk55rW002bORG86YM3/aQ==", "dev": true, "requires": { - "file-type": "^8.1.0", - "globby": "^8.0.1", - "make-dir": "^1.0.0", - "p-pipe": "^1.1.0", - "pify": "^3.0.0", - "replace-ext": "^1.0.0" + "file-type": "8.1.0", + "globby": "8.0.1", + "make-dir": "1.3.0", + "p-pipe": "1.2.0", + "pify": "3.0.0", + "replace-ext": "1.0.0" }, "dependencies": { "replace-ext": { @@ -6670,9 +6670,9 @@ "dev": true, "optional": true, "requires": { - "exec-buffer": "^3.0.0", - "gifsicle": "^4.0.0", - "is-gif": "^3.0.0" + "exec-buffer": "3.2.0", + "gifsicle": "4.0.1", + "is-gif": "3.0.0" } }, "imagemin-jpegtran": { @@ -6682,9 +6682,9 @@ "dev": true, "optional": true, "requires": { - "exec-buffer": "^3.0.0", - "is-jpg": "^2.0.0", - "jpegtran-bin": "^4.0.0" + "exec-buffer": "3.2.0", + "is-jpg": "2.0.0", + "jpegtran-bin": "4.0.0" } }, "imagemin-optipng": { @@ -6694,9 +6694,9 @@ "dev": true, "optional": true, "requires": { - "exec-buffer": "^3.0.0", - "is-png": "^1.0.0", - "optipng-bin": "^5.0.0" + "exec-buffer": "3.2.0", + "is-png": "1.1.0", + "optipng-bin": "5.0.0" } }, "imagemin-svgo": { @@ -6706,8 +6706,8 @@ "dev": true, "optional": true, "requires": { - "is-svg": "^3.0.0", - "svgo": "^1.0.5" + "is-svg": "3.0.0", + "svgo": "1.1.1" } }, "import-cwd": { @@ -6716,7 +6716,7 @@ "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", "dev": true, "requires": { - "import-from": "^2.1.0" + "import-from": "2.1.0" } }, "import-fresh": { @@ -6725,8 +6725,8 @@ "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", "dev": true, "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" + "caller-path": "2.0.0", + "resolve-from": "3.0.0" } }, "import-from": { @@ -6735,7 +6735,7 @@ "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", "dev": true, "requires": { - "resolve-from": "^3.0.0" + "resolve-from": "3.0.0" } }, "import-lazy": { @@ -6757,7 +6757,7 @@ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "^2.0.0" + "repeating": "2.0.1" } }, "indexes-of": { @@ -6784,8 +6784,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.3.3", + "wrappy": "1.0.2" } }, "inherits": { @@ -6806,19 +6806,19 @@ "integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.0", - "figures": "^2.0.0", - "lodash": "^4.17.10", + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.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.1.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.0.0", - "through": "^2.3.6" + "run-async": "2.3.0", + "rxjs": "6.3.3", + "string-width": "2.1.1", + "strip-ansi": "5.0.0", + "through": "2.3.8" }, "dependencies": { "ansi-regex": { @@ -6833,7 +6833,7 @@ "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", "dev": true, "requires": { - "ansi-regex": "^4.0.0" + "ansi-regex": "4.0.0" } } } @@ -6851,8 +6851,8 @@ "dev": true, "optional": true, "requires": { - "from2": "^2.1.1", - "p-is-promise": "^1.1.0" + "from2": "2.3.0", + "p-is-promise": "1.1.0" } }, "invariant": { @@ -6861,7 +6861,7 @@ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { - "loose-envify": "^1.0.0" + "loose-envify": "1.4.0" } }, "irregular-plurals": { @@ -6882,8 +6882,8 @@ "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", "dev": true, "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" + "is-relative": "1.0.0", + "is-windows": "1.0.2" } }, "is-absolute-url": { @@ -6898,7 +6898,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -6907,7 +6907,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -6924,7 +6924,7 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "1.12.0" } }, "is-buffer": { @@ -6939,7 +6939,7 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "^1.0.0" + "builtin-modules": "1.1.1" } }, "is-callable": { @@ -6954,12 +6954,12 @@ "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", "dev": true, "requires": { - "css-color-names": "^0.0.4", - "hex-color-regex": "^1.1.0", - "hsl-regex": "^1.0.0", - "hsla-regex": "^1.0.0", - "rgb-regex": "^1.0.1", - "rgba-regex": "^1.0.0" + "css-color-names": "0.0.4", + "hex-color-regex": "1.1.0", + "hsl-regex": "1.0.0", + "hsla-regex": "1.0.0", + "rgb-regex": "1.0.1", + "rgba-regex": "1.0.0" } }, "is-data-descriptor": { @@ -6968,7 +6968,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -6977,7 +6977,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -6994,9 +6994,9 @@ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" }, "dependencies": { "kind-of": { @@ -7025,7 +7025,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "^2.0.0" + "is-primitive": "2.0.0" } }, "is-extendable": { @@ -7046,7 +7046,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "is-fullwidth-code-point": { @@ -7062,7 +7062,7 @@ "dev": true, "optional": true, "requires": { - "file-type": "^10.4.0" + "file-type": "10.6.0" }, "dependencies": { "file-type": { @@ -7080,7 +7080,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "2.1.1" } }, "is-jpg": { @@ -7102,7 +7102,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -7111,7 +7111,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -7140,7 +7140,7 @@ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "is-png": { @@ -7174,7 +7174,7 @@ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "^1.0.1" + "has": "1.0.3" } }, "is-relative": { @@ -7183,7 +7183,7 @@ "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "requires": { - "is-unc-path": "^1.0.0" + "is-unc-path": "1.0.0" } }, "is-resolvable": { @@ -7210,7 +7210,7 @@ "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", "dev": true, "requires": { - "html-comment-regex": "^1.1.0" + "html-comment-regex": "1.1.2" } }, "is-symbol": { @@ -7219,7 +7219,7 @@ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "dev": true, "requires": { - "has-symbols": "^1.0.0" + "has-symbols": "1.0.0" } }, "is-typedarray": { @@ -7234,7 +7234,7 @@ "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, "requires": { - "unc-path-regex": "^0.1.2" + "unc-path-regex": "0.1.2" } }, "is-utf8": { @@ -7267,7 +7267,7 @@ "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", "dev": true, "requires": { - "buffer-alloc": "^1.2.0" + "buffer-alloc": "1.2.0" } }, "isexe": { @@ -7294,8 +7294,8 @@ "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", "dev": true, "requires": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" } }, "jasmine-core": { @@ -7311,9 +7311,9 @@ "dev": true, "optional": true, "requires": { - "bin-build": "^3.0.0", - "bin-wrapper": "^4.0.0", - "logalot": "^2.0.0" + "bin-build": "3.0.0", + "bin-wrapper": "4.1.0", + "logalot": "2.1.0" } }, "jquery": { @@ -7349,8 +7349,8 @@ "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "1.0.10", + "esprima": "4.0.1" } }, "jsbn": { @@ -7408,7 +7408,7 @@ "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", "dev": true, "requires": { - "minimist": "^1.2.0" + "minimist": "1.2.0" } }, "jsonfile": { @@ -7417,7 +7417,7 @@ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "4.1.15" }, "dependencies": { "graceful-fs": { @@ -7447,31 +7447,31 @@ "integrity": "sha512-NetT3wPCQMNB36uiL9LLyhrOt8SQwrEKt0xD3+KpTCfm0VxVyUJdPL5oTq2Ic5ouemgL/Iz4wqXEbF3zea9kQQ==", "dev": true, "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "chokidar": "^2.0.3", - "colors": "^1.1.0", - "combine-lists": "^1.0.0", - "connect": "^3.6.0", - "core-js": "^2.2.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.4", - "log4js": "^3.0.0", - "mime": "^2.3.1", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", + "bluebird": "3.5.3", + "body-parser": "1.18.3", + "chokidar": "2.0.4", + "colors": "1.1.2", + "combine-lists": "1.0.1", + "connect": "3.6.6", + "core-js": "2.5.7", + "di": "0.0.1", + "dom-serialize": "2.2.1", + "expand-braces": "0.1.2", + "glob": "7.1.3", + "graceful-fs": "4.1.15", + "http-proxy": "1.17.0", + "isbinaryfile": "3.0.3", + "lodash": "4.17.11", + "log4js": "3.0.6", + "mime": "2.4.0", + "minimatch": "3.0.4", + "optimist": "0.6.1", + "qjobs": "1.2.0", + "range-parser": "1.2.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", "socket.io": "2.1.1", - "source-map": "^0.6.1", + "source-map": "0.6.1", "tmp": "0.0.33", "useragent": "2.2.1" }, @@ -7482,12 +7482,12 @@ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": 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" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" } }, "graceful-fs": { @@ -7508,7 +7508,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "source-map": { @@ -7525,7 +7525,7 @@ "integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==", "dev": true, "requires": { - "jasmine-core": "^3.3" + "jasmine-core": "3.3.0" } }, "karma-phantomjs-launcher": { @@ -7534,8 +7534,8 @@ "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", "dev": true, "requires": { - "lodash": "^4.0.1", - "phantomjs-prebuilt": "^2.1.7" + "lodash": "4.17.11", + "phantomjs-prebuilt": "2.1.16" } }, "kew": { @@ -7566,7 +7566,7 @@ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true, "requires": { - "graceful-fs": "^4.1.9" + "graceful-fs": "4.1.15" }, "dependencies": { "graceful-fs": { @@ -7595,15 +7595,15 @@ "integrity": "sha512-31CmtPEZraNUtuUREYjSqRkeETFdyEHSEPAGq4erDlUXtda7pzNmctdljdIagSb589d/qXGWiiP31R5JVf+v0w==", "dev": true, "requires": { - "clone": "^2.1.2", - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "mime": "^1.4.1", - "mkdirp": "^0.5.0", - "promise": "^7.1.1", - "request": "^2.83.0", - "source-map": "~0.6.0" + "clone": "2.1.2", + "errno": "0.1.7", + "graceful-fs": "4.1.15", + "image-size": "0.5.5", + "mime": "1.4.1", + "mkdirp": "0.5.1", + "promise": "7.3.1", + "request": "2.88.0", + "source-map": "0.6.1" }, "dependencies": { "clone": { @@ -7634,8 +7634,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "1.1.2", + "type-check": "0.3.2" } }, "liftoff": { @@ -7644,14 +7644,14 @@ "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", "dev": true, "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" + "extend": "3.0.2", + "findup-sync": "2.0.0", + "fined": "1.1.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", + "rechoir": "0.6.2", + "resolve": "1.8.1" } }, "livereload-js": { @@ -7666,11 +7666,11 @@ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "graceful-fs": "4.1.15", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" }, "dependencies": { "graceful-fs": { @@ -7685,7 +7685,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "^1.2.0" + "error-ex": "1.3.2" } }, "pify": { @@ -7700,7 +7700,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } } } @@ -7735,7 +7735,7 @@ "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", "dev": true, "requires": { - "lodash._htmlescapes": "~2.4.1" + "lodash._htmlescapes": "2.4.1" } }, "lodash._escapestringchar": { @@ -7798,8 +7798,8 @@ "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", "dev": true, "requires": { - "lodash._htmlescapes": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._htmlescapes": "2.4.1", + "lodash.keys": "2.4.1" }, "dependencies": { "lodash.keys": { @@ -7808,9 +7808,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" } } } @@ -7827,7 +7827,7 @@ "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1" + "lodash._objecttypes": "2.4.1" } }, "lodash.clone": { @@ -7854,7 +7854,7 @@ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "^3.0.0" + "lodash._root": "3.0.1" } }, "lodash.flatten": { @@ -7881,7 +7881,7 @@ "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1" + "lodash._objecttypes": "2.4.1" } }, "lodash.keys": { @@ -7890,9 +7890,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" } }, "lodash.memoize": { @@ -7931,15 +7931,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" } }, "lodash.templatesettings": { @@ -7948,8 +7948,8 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" } }, "lodash.uniq": { @@ -7964,7 +7964,7 @@ "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", "dev": true, "requires": { - "lodash.keys": "~2.4.1" + "lodash.keys": "2.4.1" }, "dependencies": { "lodash.keys": { @@ -7973,9 +7973,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" } } } @@ -7986,10 +7986,10 @@ "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "rfdc": "^1.1.2", + "circular-json": "0.5.9", + "date-format": "1.2.0", + "debug": "3.2.6", + "rfdc": "1.1.2", "streamroller": "0.7.0" }, "dependencies": { @@ -8005,7 +8005,7 @@ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } } } @@ -8017,8 +8017,8 @@ "dev": true, "optional": true, "requires": { - "figures": "^1.3.5", - "squeak": "^1.0.0" + "figures": "1.7.0", + "squeak": "1.3.0" }, "dependencies": { "figures": { @@ -8028,8 +8028,8 @@ "dev": true, "optional": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" } }, "object-assign": { @@ -8053,7 +8053,7 @@ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" + "js-tokens": "4.0.0" } }, "loud-rejection": { @@ -8062,8 +8062,8 @@ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" } }, "lowercase-keys": { @@ -8079,10 +8079,10 @@ "dev": true, "optional": true, "requires": { - "get-stdin": "^4.0.1", - "indent-string": "^2.1.0", - "longest": "^1.0.0", - "meow": "^3.3.0" + "get-stdin": "4.0.1", + "indent-string": "2.1.0", + "longest": "1.0.1", + "meow": "3.7.0" } }, "lru-cache": { @@ -8097,7 +8097,7 @@ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" } }, "make-iterator": { @@ -8106,7 +8106,7 @@ "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", "dev": true, "requires": { - "kind-of": "^6.0.2" + "kind-of": "6.0.2" } }, "map-cache": { @@ -8133,7 +8133,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "^1.0.0" + "object-visit": "1.0.1" } }, "marked": { @@ -8166,16 +8166,16 @@ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" }, "dependencies": { "object-assign": { @@ -8192,7 +8192,7 @@ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "dev": true, "requires": { - "readable-stream": "^2.0.1" + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -8207,13 +8207,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -8222,7 +8222,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -8239,19 +8239,19 @@ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "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" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "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.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "mime": { @@ -8272,7 +8272,7 @@ "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "dev": true, "requires": { - "mime-db": "~1.37.0" + "mime-db": "1.37.0" } }, "mimic-fn": { @@ -8293,7 +8293,7 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "^1.0.0" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -8308,8 +8308,8 @@ "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "for-in": "1.0.2", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -8318,7 +8318,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -8379,17 +8379,17 @@ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "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" + "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.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "natives": { @@ -8427,7 +8427,7 @@ "integrity": "sha512-Ky7q0BO1BBkG/rQz6PkEZ59rwo+aSfhczHP1wwq8IowoVdN/FpiP7qp0XW0P2+BVCWe5fQUBozdbVd54q1RbCQ==", "dev": true, "requires": { - "semver": "^5.3.0" + "semver": "5.6.0" } }, "node.extend": { @@ -8436,8 +8436,8 @@ "integrity": "sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA==", "dev": true, "requires": { - "has": "^1.0.3", - "is": "^3.2.1" + "has": "1.0.3", + "is": "3.2.1" } }, "normalize-package-data": { @@ -8446,10 +8446,10 @@ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.6.0", + "validate-npm-package-license": "3.0.4" } }, "normalize-path": { @@ -8458,7 +8458,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "remove-trailing-separator": "1.1.0" } }, "normalize-range": { @@ -8483,132 +8483,132 @@ "resolved": "https://registry.npmjs.org/npm/-/npm-6.4.1.tgz", "integrity": "sha512-mXJL1NTVU136PtuopXCUQaNWuHlXCTp4McwlSW8S9/Aj8OEPAlSBgo8og7kJ01MjCDrkmqFQTvN5tTEhBMhXQg==", "requires": { - "JSONStream": "^1.3.4", - "abbrev": "~1.1.1", - "ansicolors": "~0.3.2", - "ansistyles": "~0.1.3", - "aproba": "~1.2.0", - "archy": "~1.0.0", - "bin-links": "^1.1.2", - "bluebird": "~3.5.1", - "byte-size": "^4.0.3", - "cacache": "^11.2.0", - "call-limit": "~1.1.0", - "chownr": "~1.0.1", - "ci-info": "^1.4.0", - "cli-columns": "^3.1.2", - "cli-table3": "^0.5.0", - "cmd-shim": "~2.0.2", - "columnify": "~1.5.4", - "config-chain": "~1.1.11", - "debuglog": "*", - "detect-indent": "~5.0.0", - "detect-newline": "^2.1.0", - "dezalgo": "~1.0.3", - "editor": "~1.0.0", - "figgy-pudding": "^3.4.1", - "find-npm-prefix": "^1.0.2", - "fs-vacuum": "~1.2.10", - "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.0.1", - "glob": "~7.1.2", - "graceful-fs": "~4.1.11", - "has-unicode": "~2.0.1", - "hosted-git-info": "^2.7.1", - "iferr": "^1.0.2", - "imurmurhash": "*", - "inflight": "~1.0.6", - "inherits": "~2.0.3", - "ini": "^1.3.5", - "init-package-json": "^1.10.3", - "is-cidr": "^2.0.6", - "json-parse-better-errors": "^1.0.2", - "lazy-property": "~1.0.0", - "libcipm": "^2.0.2", - "libnpmhook": "^4.0.1", - "libnpx": "^10.2.0", - "lock-verify": "^2.0.2", - "lockfile": "^1.0.4", - "lodash._baseindexof": "*", - "lodash._baseuniq": "~4.6.0", - "lodash._bindcallback": "*", - "lodash._cacheindexof": "*", - "lodash._createcache": "*", - "lodash._getnative": "*", - "lodash.clonedeep": "~4.5.0", - "lodash.restparam": "*", - "lodash.union": "~4.6.0", - "lodash.uniq": "~4.5.0", - "lodash.without": "~4.4.0", - "lru-cache": "^4.1.3", - "meant": "~1.0.1", - "mississippi": "^3.0.0", - "mkdirp": "~0.5.1", - "move-concurrently": "^1.0.1", - "node-gyp": "^3.8.0", - "nopt": "~4.0.1", - "normalize-package-data": "~2.4.0", - "npm-audit-report": "^1.3.1", - "npm-cache-filename": "~1.0.2", - "npm-install-checks": "~3.0.0", - "npm-lifecycle": "^2.1.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.11", - "npm-pick-manifest": "^2.1.0", - "npm-profile": "^3.0.2", - "npm-registry-client": "^8.6.0", - "npm-registry-fetch": "^1.1.0", - "npm-user-validate": "~1.0.0", - "npmlog": "~4.1.2", - "once": "~1.4.0", - "opener": "^1.5.0", - "osenv": "^0.1.5", - "pacote": "^8.1.6", - "path-is-inside": "~1.0.2", - "promise-inflight": "~1.0.1", - "qrcode-terminal": "^0.12.0", - "query-string": "^6.1.0", - "qw": "~1.0.1", - "read": "~1.0.7", - "read-cmd-shim": "~1.0.1", - "read-installed": "~4.0.3", - "read-package-json": "^2.0.13", - "read-package-tree": "^5.2.1", - "readable-stream": "^2.3.6", - "readdir-scoped-modules": "*", - "request": "^2.88.0", - "retry": "^0.12.0", - "rimraf": "~2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.5.0", - "sha": "~2.0.1", - "slide": "~1.1.6", - "sorted-object": "~2.0.1", - "sorted-union-stream": "~2.1.3", - "ssri": "^6.0.0", - "stringify-package": "^1.0.0", - "tar": "^4.4.6", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", + "JSONStream": "1.3.4", + "abbrev": "1.1.1", + "ansicolors": "0.3.2", + "ansistyles": "0.1.3", + "aproba": "1.2.0", + "archy": "1.0.0", + "bin-links": "1.1.2", + "bluebird": "3.5.1", + "byte-size": "4.0.3", + "cacache": "11.2.0", + "call-limit": "1.1.0", + "chownr": "1.0.1", + "ci-info": "1.4.0", + "cli-columns": "3.1.2", + "cli-table3": "0.5.0", + "cmd-shim": "2.0.2", + "columnify": "1.5.4", + "config-chain": "1.1.11", + "debuglog": "1.0.1", + "detect-indent": "5.0.0", + "detect-newline": "2.1.0", + "dezalgo": "1.0.3", + "editor": "1.0.0", + "figgy-pudding": "3.4.1", + "find-npm-prefix": "1.0.2", + "fs-vacuum": "1.2.10", + "fs-write-stream-atomic": "1.0.10", + "gentle-fs": "2.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "has-unicode": "2.0.1", + "hosted-git-info": "2.7.1", + "iferr": "1.0.2", + "imurmurhash": "0.1.4", + "inflight": "1.0.6", + "inherits": "2.0.3", + "ini": "1.3.5", + "init-package-json": "1.10.3", + "is-cidr": "2.0.6", + "json-parse-better-errors": "1.0.2", + "lazy-property": "1.0.0", + "libcipm": "2.0.2", + "libnpmhook": "4.0.1", + "libnpx": "10.2.0", + "lock-verify": "2.0.2", + "lockfile": "1.0.4", + "lodash._baseindexof": "3.1.0", + "lodash._baseuniq": "4.6.0", + "lodash._bindcallback": "3.0.1", + "lodash._cacheindexof": "3.0.2", + "lodash._createcache": "3.1.2", + "lodash._getnative": "3.9.1", + "lodash.clonedeep": "4.5.0", + "lodash.restparam": "3.6.1", + "lodash.union": "4.6.0", + "lodash.uniq": "4.5.0", + "lodash.without": "4.4.0", + "lru-cache": "4.1.3", + "meant": "1.0.1", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "node-gyp": "3.8.0", + "nopt": "4.0.1", + "normalize-package-data": "2.4.0", + "npm-audit-report": "1.3.1", + "npm-cache-filename": "1.0.2", + "npm-install-checks": "3.0.0", + "npm-lifecycle": "2.1.0", + "npm-package-arg": "6.1.0", + "npm-packlist": "1.1.11", + "npm-pick-manifest": "2.1.0", + "npm-profile": "3.0.2", + "npm-registry-client": "8.6.0", + "npm-registry-fetch": "1.1.0", + "npm-user-validate": "1.0.0", + "npmlog": "4.1.2", + "once": "1.4.0", + "opener": "1.5.0", + "osenv": "0.1.5", + "pacote": "8.1.6", + "path-is-inside": "1.0.2", + "promise-inflight": "1.0.1", + "qrcode-terminal": "0.12.0", + "query-string": "6.1.0", + "qw": "1.0.1", + "read": "1.0.7", + "read-cmd-shim": "1.0.1", + "read-installed": "4.0.3", + "read-package-json": "2.0.13", + "read-package-tree": "5.2.1", + "readable-stream": "2.3.6", + "readdir-scoped-modules": "1.0.2", + "request": "2.88.0", + "retry": "0.12.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "sha": "2.0.1", + "slide": "1.1.6", + "sorted-object": "2.0.1", + "sorted-union-stream": "2.1.3", + "ssri": "6.0.0", + "stringify-package": "1.0.0", + "tar": "4.4.6", + "text-table": "0.2.0", + "tiny-relative-date": "1.3.0", "uid-number": "0.0.6", - "umask": "~1.1.0", - "unique-filename": "~1.1.0", - "unpipe": "~1.0.0", - "update-notifier": "^2.5.0", - "uuid": "^3.3.2", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "~3.0.0", - "which": "^1.3.1", - "worker-farm": "^1.6.0", - "write-file-atomic": "^2.3.0" + "umask": "1.1.0", + "unique-filename": "1.1.0", + "unpipe": "1.0.0", + "update-notifier": "2.5.0", + "uuid": "3.3.2", + "validate-npm-package-license": "3.0.4", + "validate-npm-package-name": "3.0.0", + "which": "1.3.1", + "worker-farm": "1.6.0", + "write-file-atomic": "2.3.0" }, "dependencies": { "JSONStream": { "version": "1.3.4", "bundled": true, "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" + "jsonparse": "1.3.1", + "through": "2.3.8" } }, "abbrev": { @@ -8619,31 +8619,31 @@ "version": "4.2.0", "bundled": true, "requires": { - "es6-promisify": "^5.0.0" + "es6-promisify": "5.0.0" } }, "agentkeepalive": { "version": "3.4.1", "bundled": true, "requires": { - "humanize-ms": "^1.2.1" + "humanize-ms": "1.2.1" } }, "ajv": { "version": "5.5.2", "bundled": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, "ansi-align": { "version": "2.0.0", "bundled": true, "requires": { - "string-width": "^2.0.0" + "string-width": "2.1.1" } }, "ansi-regex": { @@ -8654,7 +8654,7 @@ "version": "3.2.1", "bundled": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.1" } }, "ansicolors": { @@ -8677,8 +8677,8 @@ "version": "1.1.4", "bundled": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "delegates": "1.0.0", + "readable-stream": "2.3.6" } }, "asap": { @@ -8689,7 +8689,7 @@ "version": "0.2.4", "bundled": true, "requires": { - "safer-buffer": "~2.1.0" + "safer-buffer": "2.1.2" } }, "assert-plus": { @@ -8717,25 +8717,25 @@ "bundled": true, "optional": true, "requires": { - "tweetnacl": "^0.14.3" + "tweetnacl": "0.14.5" } }, "bin-links": { "version": "1.1.2", "bundled": true, "requires": { - "bluebird": "^3.5.0", - "cmd-shim": "^2.0.2", - "gentle-fs": "^2.0.0", - "graceful-fs": "^4.1.11", - "write-file-atomic": "^2.3.0" + "bluebird": "3.5.1", + "cmd-shim": "2.0.2", + "gentle-fs": "2.0.1", + "graceful-fs": "4.1.11", + "write-file-atomic": "2.3.0" } }, "block-stream": { "version": "0.0.9", "bundled": true, "requires": { - "inherits": "~2.0.0" + "inherits": "2.0.3" } }, "bluebird": { @@ -8746,20 +8746,20 @@ "version": "1.3.0", "bundled": true, "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.4.1", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "2.0.0" } }, "brace-expansion": { "version": "1.1.11", "bundled": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, @@ -8787,20 +8787,20 @@ "version": "11.2.0", "bundled": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", - "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.0", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" + "bluebird": "3.5.1", + "chownr": "1.0.1", + "figgy-pudding": "3.4.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "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.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" } }, "call-limit": { @@ -8823,9 +8823,9 @@ "version": "2.4.1", "bundled": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" } }, "chownr": { @@ -8840,7 +8840,7 @@ "version": "2.0.9", "bundled": true, "requires": { - "ip-regex": "^2.1.0" + "ip-regex": "2.1.0" } }, "cli-boxes": { @@ -8851,26 +8851,26 @@ "version": "3.1.2", "bundled": true, "requires": { - "string-width": "^2.0.0", - "strip-ansi": "^3.0.1" + "string-width": "2.1.1", + "strip-ansi": "3.0.1" } }, "cli-table3": { "version": "0.5.0", "bundled": true, "requires": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^2.1.1" + "colors": "1.1.2", + "object-assign": "4.1.1", + "string-width": "2.1.1" } }, "cliui": { "version": "4.1.0", "bundled": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" }, "dependencies": { "ansi-regex": { @@ -8881,7 +8881,7 @@ "version": "4.0.0", "bundled": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -8894,8 +8894,8 @@ "version": "2.0.2", "bundled": true, "requires": { - "graceful-fs": "^4.1.2", - "mkdirp": "~0.5.0" + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1" } }, "co": { @@ -8910,7 +8910,7 @@ "version": "1.9.1", "bundled": true, "requires": { - "color-name": "^1.1.1" + "color-name": "1.1.3" } }, "color-name": { @@ -8926,15 +8926,15 @@ "version": "1.5.4", "bundled": true, "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" + "strip-ansi": "3.0.1", + "wcwidth": "1.0.1" } }, "combined-stream": { "version": "1.0.6", "bundled": true, "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "concat-map": { @@ -8945,30 +8945,30 @@ "version": "1.6.2", "bundled": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "buffer-from": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" } }, "config-chain": { "version": "1.1.11", "bundled": true, "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" + "ini": "1.3.5", + "proto-list": "1.2.4" } }, "configstore": { "version": "3.1.2", "bundled": true, "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.3.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" } }, "console-control-strings": { @@ -8979,12 +8979,12 @@ "version": "1.0.5", "bundled": true, "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" + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" }, "dependencies": { "iferr": { @@ -9001,16 +9001,16 @@ "version": "3.0.2", "bundled": true, "requires": { - "capture-stack-trace": "^1.0.0" + "capture-stack-trace": "1.0.0" } }, "cross-spawn": { "version": "5.1.0", "bundled": true, "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" } }, "crypto-random-string": { @@ -9025,7 +9025,7 @@ "version": "1.14.1", "bundled": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "debug": { @@ -9061,7 +9061,7 @@ "version": "1.0.3", "bundled": true, "requires": { - "clone": "^1.0.2" + "clone": "1.0.4" } }, "delayed-stream": { @@ -9084,15 +9084,15 @@ "version": "1.0.3", "bundled": true, "requires": { - "asap": "^2.0.0", - "wrappy": "1" + "asap": "2.0.6", + "wrappy": "1.0.2" } }, "dot-prop": { "version": "4.2.0", "bundled": true, "requires": { - "is-obj": "^1.0.0" + "is-obj": "1.0.1" } }, "dotenv": { @@ -9107,10 +9107,10 @@ "version": "3.6.0", "bundled": true, "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" } }, "ecc-jsbn": { @@ -9118,8 +9118,8 @@ "bundled": true, "optional": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" } }, "editor": { @@ -9130,14 +9130,14 @@ "version": "0.1.12", "bundled": true, "requires": { - "iconv-lite": "~0.4.13" + "iconv-lite": "0.4.23" } }, "end-of-stream": { "version": "1.4.1", "bundled": true, "requires": { - "once": "^1.4.0" + "once": "1.4.0" } }, "err-code": { @@ -9148,7 +9148,7 @@ "version": "0.1.7", "bundled": true, "requires": { - "prr": "~1.0.1" + "prr": "1.0.1" } }, "es6-promise": { @@ -9159,7 +9159,7 @@ "version": "5.0.0", "bundled": true, "requires": { - "es6-promise": "^4.0.3" + "es6-promise": "4.2.4" } }, "escape-string-regexp": { @@ -9170,13 +9170,13 @@ "version": "0.7.0", "bundled": true, "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.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" + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" } }, "extend": { @@ -9207,15 +9207,15 @@ "version": "2.1.0", "bundled": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "2.0.0" } }, "flush-write-stream": { "version": "1.0.3", "bundled": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" + "inherits": "2.0.3", + "readable-stream": "2.3.6" } }, "forever-agent": { @@ -9226,43 +9226,43 @@ "version": "2.3.2", "bundled": true, "requires": { - "asynckit": "^0.4.0", + "asynckit": "0.4.0", "combined-stream": "1.0.6", - "mime-types": "^2.1.12" + "mime-types": "2.1.19" } }, "from2": { "version": "2.3.0", "bundled": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" + "inherits": "2.0.3", + "readable-stream": "2.3.6" } }, "fs-minipass": { "version": "1.2.5", "bundled": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.3.3" } }, "fs-vacuum": { "version": "1.2.10", "bundled": true, "requires": { - "graceful-fs": "^4.1.2", - "path-is-inside": "^1.0.1", - "rimraf": "^2.5.2" + "graceful-fs": "4.1.11", + "path-is-inside": "1.0.2", + "rimraf": "2.6.2" } }, "fs-write-stream-atomic": { "version": "1.0.10", "bundled": true, "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "imurmurhash": "0.1.4", + "readable-stream": "2.3.6" }, "dependencies": { "iferr": { @@ -9279,33 +9279,33 @@ "version": "1.0.11", "bundled": true, "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" } }, "gauge": { "version": "2.7.4", "bundled": 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" + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" }, "dependencies": { "string-width": { "version": "1.0.2", "bundled": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } } } @@ -9318,14 +9318,14 @@ "version": "2.0.1", "bundled": true, "requires": { - "aproba": "^1.1.2", - "fs-vacuum": "^1.2.10", - "graceful-fs": "^4.1.11", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "path-is-inside": "^1.0.2", - "read-cmd-shim": "^1.0.1", - "slide": "^1.1.6" + "aproba": "1.2.0", + "fs-vacuum": "1.2.10", + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "path-is-inside": "1.0.2", + "read-cmd-shim": "1.0.1", + "slide": "1.1.6" }, "dependencies": { "iferr": { @@ -9346,43 +9346,43 @@ "version": "0.1.7", "bundled": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "glob": { "version": "7.1.2", "bundled": 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" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "global-dirs": { "version": "0.1.1", "bundled": true, "requires": { - "ini": "^1.3.4" + "ini": "1.3.5" } }, "got": { "version": "6.7.1", "bundled": true, "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" } }, "graceful-fs": { @@ -9397,8 +9397,8 @@ "version": "5.1.0", "bundled": true, "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" + "ajv": "5.5.2", + "har-schema": "2.0.0" } }, "has-flag": { @@ -9421,7 +9421,7 @@ "version": "2.1.0", "bundled": true, "requires": { - "agent-base": "4", + "agent-base": "4.2.0", "debug": "3.1.0" } }, @@ -9429,31 +9429,31 @@ "version": "1.2.0", "bundled": true, "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" } }, "https-proxy-agent": { "version": "2.2.1", "bundled": true, "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" + "agent-base": "4.2.0", + "debug": "3.1.0" } }, "humanize-ms": { "version": "1.2.1", "bundled": true, "requires": { - "ms": "^2.0.0" + "ms": "2.1.1" } }, "iconv-lite": { "version": "0.4.23", "bundled": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } }, "iferr": { @@ -9464,7 +9464,7 @@ "version": "3.0.1", "bundled": true, "requires": { - "minimatch": "^3.0.4" + "minimatch": "3.0.4" } }, "import-lazy": { @@ -9479,8 +9479,8 @@ "version": "1.0.6", "bundled": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -9495,14 +9495,14 @@ "version": "1.10.3", "bundled": true, "requires": { - "glob": "^7.1.1", - "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "1 || 2", - "semver": "2.x || 3.x || 4 || 5", - "validate-npm-package-license": "^3.0.1", - "validate-npm-package-name": "^3.0.0" + "glob": "7.1.2", + "npm-package-arg": "6.1.0", + "promzard": "0.3.0", + "read": "1.0.7", + "read-package-json": "2.0.13", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.4", + "validate-npm-package-name": "3.0.0" } }, "invert-kv": { @@ -9521,36 +9521,36 @@ "version": "1.0.0", "bundled": true, "requires": { - "builtin-modules": "^1.0.0" + "builtin-modules": "1.1.1" } }, "is-ci": { "version": "1.1.0", "bundled": true, "requires": { - "ci-info": "^1.0.0" + "ci-info": "1.4.0" } }, "is-cidr": { "version": "2.0.6", "bundled": true, "requires": { - "cidr-regex": "^2.0.8" + "cidr-regex": "2.0.9" } }, "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "is-installed-globally": { "version": "0.1.0", "bundled": true, "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" } }, "is-npm": { @@ -9565,7 +9565,7 @@ "version": "1.0.1", "bundled": true, "requires": { - "path-is-inside": "^1.0.1" + "path-is-inside": "1.0.2" } }, "is-redirect": { @@ -9635,7 +9635,7 @@ "version": "3.1.0", "bundled": true, "requires": { - "package-json": "^4.0.0" + "package-json": "4.0.1" } }, "lazy-property": { @@ -9646,46 +9646,46 @@ "version": "1.0.0", "bundled": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "1.0.0" } }, "libcipm": { "version": "2.0.2", "bundled": true, "requires": { - "bin-links": "^1.1.2", - "bluebird": "^3.5.1", - "find-npm-prefix": "^1.0.2", - "graceful-fs": "^4.1.11", - "lock-verify": "^2.0.2", - "mkdirp": "^0.5.1", - "npm-lifecycle": "^2.0.3", - "npm-logical-tree": "^1.2.1", - "npm-package-arg": "^6.1.0", - "pacote": "^8.1.6", - "protoduck": "^5.0.0", - "read-package-json": "^2.0.13", - "rimraf": "^2.6.2", - "worker-farm": "^1.6.0" + "bin-links": "1.1.2", + "bluebird": "3.5.1", + "find-npm-prefix": "1.0.2", + "graceful-fs": "4.1.11", + "lock-verify": "2.0.2", + "mkdirp": "0.5.1", + "npm-lifecycle": "2.1.0", + "npm-logical-tree": "1.2.1", + "npm-package-arg": "6.1.0", + "pacote": "8.1.6", + "protoduck": "5.0.0", + "read-package-json": "2.0.13", + "rimraf": "2.6.2", + "worker-farm": "1.6.0" } }, "libnpmhook": { "version": "4.0.1", "bundled": true, "requires": { - "figgy-pudding": "^3.1.0", - "npm-registry-fetch": "^3.0.0" + "figgy-pudding": "3.4.1", + "npm-registry-fetch": "3.1.1" }, "dependencies": { "npm-registry-fetch": { "version": "3.1.1", "bundled": true, "requires": { - "bluebird": "^3.5.1", - "figgy-pudding": "^3.1.0", - "lru-cache": "^4.1.2", - "make-fetch-happen": "^4.0.0", - "npm-package-arg": "^6.0.0" + "bluebird": "3.5.1", + "figgy-pudding": "3.4.1", + "lru-cache": "4.1.3", + "make-fetch-happen": "4.0.1", + "npm-package-arg": "6.1.0" } } } @@ -9694,37 +9694,37 @@ "version": "10.2.0", "bundled": true, "requires": { - "dotenv": "^5.0.1", - "npm-package-arg": "^6.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.0", - "update-notifier": "^2.3.0", - "which": "^1.3.0", - "y18n": "^4.0.0", - "yargs": "^11.0.0" + "dotenv": "5.0.1", + "npm-package-arg": "6.1.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "update-notifier": "2.5.0", + "which": "1.3.1", + "y18n": "4.0.0", + "yargs": "11.0.0" } }, "locate-path": { "version": "2.0.0", "bundled": true, "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "2.0.0", + "path-exists": "3.0.0" } }, "lock-verify": { "version": "2.0.2", "bundled": true, "requires": { - "npm-package-arg": "^5.1.2 || 6", - "semver": "^5.4.1" + "npm-package-arg": "6.1.0", + "semver": "5.5.0" } }, "lockfile": { "version": "1.0.4", "bundled": true, "requires": { - "signal-exit": "^3.0.2" + "signal-exit": "3.0.2" } }, "lodash._baseindexof": { @@ -9735,8 +9735,8 @@ "version": "4.6.0", "bundled": true, "requires": { - "lodash._createset": "~4.0.0", - "lodash._root": "~3.0.0" + "lodash._createset": "4.0.3", + "lodash._root": "3.0.1" } }, "lodash._bindcallback": { @@ -9751,7 +9751,7 @@ "version": "3.1.2", "bundled": true, "requires": { - "lodash._getnative": "^3.0.0" + "lodash._getnative": "3.9.1" } }, "lodash._createset": { @@ -9794,32 +9794,32 @@ "version": "4.1.3", "bundled": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } }, "make-dir": { "version": "1.3.0", "bundled": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" } }, "make-fetch-happen": { "version": "4.0.1", "bundled": true, "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^11.0.1", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^4.0.0", - "ssri": "^6.0.0" + "agentkeepalive": "3.4.1", + "cacache": "11.2.0", + "http-cache-semantics": "3.8.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "node-fetch-npm": "2.0.2", + "promise-retry": "1.1.1", + "socks-proxy-agent": "4.0.1", + "ssri": "6.0.0" } }, "meant": { @@ -9830,7 +9830,7 @@ "version": "1.1.0", "bundled": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "1.2.0" } }, "mime-db": { @@ -9841,7 +9841,7 @@ "version": "2.1.19", "bundled": true, "requires": { - "mime-db": "~1.35.0" + "mime-db": "1.35.0" } }, "mimic-fn": { @@ -9852,7 +9852,7 @@ "version": "3.0.4", "bundled": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -9863,8 +9863,8 @@ "version": "2.3.3", "bundled": true, "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "safe-buffer": "5.1.2", + "yallist": "3.0.2" }, "dependencies": { "yallist": { @@ -9877,23 +9877,23 @@ "version": "1.1.0", "bundled": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.3.3" } }, "mississippi": { "version": "3.0.0", "bundled": true, "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" + "concat-stream": "1.6.2", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "3.0.0", + "pumpify": "1.5.1", + "stream-each": "1.2.2", + "through2": "2.0.3" } }, "mkdirp": { @@ -9907,12 +9907,12 @@ "version": "1.0.1", "bundled": true, "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" + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" } }, "ms": { @@ -9927,34 +9927,34 @@ "version": "2.0.2", "bundled": true, "requires": { - "encoding": "^0.1.11", - "json-parse-better-errors": "^1.0.0", - "safe-buffer": "^5.1.1" + "encoding": "0.1.12", + "json-parse-better-errors": "1.0.2", + "safe-buffer": "5.1.2" } }, "node-gyp": { "version": "3.8.0", "bundled": true, "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" + "fstream": "1.0.11", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.5", + "request": "2.88.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.1" }, "dependencies": { "nopt": { "version": "3.0.6", "bundled": true, "requires": { - "abbrev": "1" + "abbrev": "1.1.1" } }, "semver": { @@ -9965,9 +9965,9 @@ "version": "2.2.1", "bundled": true, "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" } } } @@ -9976,26 +9976,26 @@ "version": "4.0.1", "bundled": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1.1.1", + "osenv": "0.1.5" } }, "normalize-package-data": { "version": "2.4.0", "bundled": true, "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.4" } }, "npm-audit-report": { "version": "1.3.1", "bundled": true, "requires": { - "cli-table3": "^0.5.0", - "console-control-strings": "^1.1.0" + "cli-table3": "0.5.0", + "console-control-strings": "1.1.0" } }, "npm-bundled": { @@ -10010,21 +10010,21 @@ "version": "3.0.0", "bundled": true, "requires": { - "semver": "^2.3.0 || 3.x || 4 || 5" + "semver": "5.5.0" } }, "npm-lifecycle": { "version": "2.1.0", "bundled": true, "requires": { - "byline": "^5.0.0", - "graceful-fs": "^4.1.11", - "node-gyp": "^3.8.0", - "resolve-from": "^4.0.0", - "slide": "^1.1.6", + "byline": "5.0.0", + "graceful-fs": "4.1.11", + "node-gyp": "3.8.0", + "resolve-from": "4.0.0", + "slide": "1.1.6", "uid-number": "0.0.6", - "umask": "^1.1.0", - "which": "^1.3.1" + "umask": "1.1.0", + "which": "1.3.1" } }, "npm-logical-tree": { @@ -10035,52 +10035,52 @@ "version": "6.1.0", "bundled": true, "requires": { - "hosted-git-info": "^2.6.0", - "osenv": "^0.1.5", - "semver": "^5.5.0", - "validate-npm-package-name": "^3.0.0" + "hosted-git-info": "2.7.1", + "osenv": "0.1.5", + "semver": "5.5.0", + "validate-npm-package-name": "3.0.0" } }, "npm-packlist": { "version": "1.1.11", "bundled": true, "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.5" } }, "npm-pick-manifest": { "version": "2.1.0", "bundled": true, "requires": { - "npm-package-arg": "^6.0.0", - "semver": "^5.4.1" + "npm-package-arg": "6.1.0", + "semver": "5.5.0" } }, "npm-profile": { "version": "3.0.2", "bundled": true, "requires": { - "aproba": "^1.1.2 || 2", - "make-fetch-happen": "^2.5.0 || 3 || 4" + "aproba": "1.2.0", + "make-fetch-happen": "4.0.1" } }, "npm-registry-client": { "version": "8.6.0", "bundled": true, "requires": { - "concat-stream": "^1.5.2", - "graceful-fs": "^4.1.6", - "normalize-package-data": "~1.0.1 || ^2.0.0", - "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", - "npmlog": "2 || ^3.1.0 || ^4.0.0", - "once": "^1.3.3", - "request": "^2.74.0", - "retry": "^0.10.0", - "safe-buffer": "^5.1.1", - "semver": "2 >=2.2.1 || 3.x || 4 || 5", - "slide": "^1.1.3", - "ssri": "^5.2.4" + "concat-stream": "1.6.2", + "graceful-fs": "4.1.11", + "normalize-package-data": "2.4.0", + "npm-package-arg": "6.1.0", + "npmlog": "4.1.2", + "once": "1.4.0", + "request": "2.88.0", + "retry": "0.10.1", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "slide": "1.1.6", + "ssri": "5.3.0" }, "dependencies": { "retry": { @@ -10091,7 +10091,7 @@ "version": "5.3.0", "bundled": true, "requires": { - "safe-buffer": "^5.1.1" + "safe-buffer": "5.1.2" } } } @@ -10100,47 +10100,47 @@ "version": "1.1.0", "bundled": true, "requires": { - "bluebird": "^3.5.1", - "figgy-pudding": "^2.0.1", - "lru-cache": "^4.1.2", - "make-fetch-happen": "^3.0.0", - "npm-package-arg": "^6.0.0", - "safe-buffer": "^5.1.1" + "bluebird": "3.5.1", + "figgy-pudding": "2.0.1", + "lru-cache": "4.1.3", + "make-fetch-happen": "3.0.0", + "npm-package-arg": "6.1.0", + "safe-buffer": "5.1.2" }, "dependencies": { "cacache": { "version": "10.0.4", "bundled": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "mississippi": "2.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.3.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" }, "dependencies": { "mississippi": { "version": "2.0.0", "bundled": true, "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": "^2.0.1", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" + "concat-stream": "1.6.2", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "2.0.1", + "pumpify": "1.5.1", + "stream-each": "1.2.2", + "through2": "2.0.3" } } } @@ -10153,25 +10153,25 @@ "version": "3.0.0", "bundled": true, "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^10.0.4", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.0", - "lru-cache": "^4.1.2", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^3.0.1", - "ssri": "^5.2.4" + "agentkeepalive": "3.4.1", + "cacache": "10.0.4", + "http-cache-semantics": "3.8.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "node-fetch-npm": "2.0.2", + "promise-retry": "1.1.1", + "socks-proxy-agent": "3.0.1", + "ssri": "5.3.0" } }, "pump": { "version": "2.0.1", "bundled": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.1", + "once": "1.4.0" } }, "smart-buffer": { @@ -10182,23 +10182,23 @@ "version": "1.1.10", "bundled": true, "requires": { - "ip": "^1.1.4", - "smart-buffer": "^1.0.13" + "ip": "1.1.5", + "smart-buffer": "1.1.15" } }, "socks-proxy-agent": { "version": "3.0.1", "bundled": true, "requires": { - "agent-base": "^4.1.0", - "socks": "^1.1.10" + "agent-base": "4.2.0", + "socks": "1.1.10" } }, "ssri": { "version": "5.3.0", "bundled": true, "requires": { - "safe-buffer": "^5.1.1" + "safe-buffer": "5.1.2" } } } @@ -10207,7 +10207,7 @@ "version": "2.0.2", "bundled": true, "requires": { - "path-key": "^2.0.0" + "path-key": "2.0.1" } }, "npm-user-validate": { @@ -10218,10 +10218,10 @@ "version": "4.1.2", "bundled": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" } }, "number-is-nan": { @@ -10240,7 +10240,7 @@ "version": "1.4.0", "bundled": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "opener": { @@ -10255,9 +10255,9 @@ "version": "2.1.0", "bundled": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" } }, "os-tmpdir": { @@ -10268,8 +10268,8 @@ "version": "0.1.5", "bundled": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, "p-finally": { @@ -10280,14 +10280,14 @@ "version": "1.2.0", "bundled": true, "requires": { - "p-try": "^1.0.0" + "p-try": "1.0.0" } }, "p-locate": { "version": "2.0.0", "bundled": true, "requires": { - "p-limit": "^1.1.0" + "p-limit": "1.2.0" } }, "p-try": { @@ -10298,50 +10298,50 @@ "version": "4.0.1", "bundled": true, "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" + "got": "6.7.1", + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0", + "semver": "5.5.0" } }, "pacote": { "version": "8.1.6", "bundled": true, "requires": { - "bluebird": "^3.5.1", - "cacache": "^11.0.2", - "get-stream": "^3.0.0", - "glob": "^7.1.2", - "lru-cache": "^4.1.3", - "make-fetch-happen": "^4.0.1", - "minimatch": "^3.0.4", - "minipass": "^2.3.3", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "normalize-package-data": "^2.4.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.10", - "npm-pick-manifest": "^2.1.0", - "osenv": "^0.1.5", - "promise-inflight": "^1.0.1", - "promise-retry": "^1.1.1", - "protoduck": "^5.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.5.0", - "ssri": "^6.0.0", - "tar": "^4.4.3", - "unique-filename": "^1.1.0", - "which": "^1.3.0" + "bluebird": "3.5.1", + "cacache": "11.2.0", + "get-stream": "3.0.0", + "glob": "7.1.2", + "lru-cache": "4.1.3", + "make-fetch-happen": "4.0.1", + "minimatch": "3.0.4", + "minipass": "2.3.3", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "normalize-package-data": "2.4.0", + "npm-package-arg": "6.1.0", + "npm-packlist": "1.1.11", + "npm-pick-manifest": "2.1.0", + "osenv": "0.1.5", + "promise-inflight": "1.0.1", + "promise-retry": "1.1.1", + "protoduck": "5.0.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "ssri": "6.0.0", + "tar": "4.4.6", + "unique-filename": "1.1.0", + "which": "1.3.1" } }, "parallel-transform": { "version": "1.1.0", "bundled": true, "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.6" } }, "path-exists": { @@ -10384,8 +10384,8 @@ "version": "1.1.1", "bundled": true, "requires": { - "err-code": "^1.0.0", - "retry": "^0.10.0" + "err-code": "1.1.2", + "retry": "0.10.1" }, "dependencies": { "retry": { @@ -10398,7 +10398,7 @@ "version": "0.3.0", "bundled": true, "requires": { - "read": "1" + "read": "1.0.7" } }, "proto-list": { @@ -10409,7 +10409,7 @@ "version": "5.0.0", "bundled": true, "requires": { - "genfun": "^4.0.1" + "genfun": "4.0.1" } }, "prr": { @@ -10428,25 +10428,25 @@ "version": "3.0.0", "bundled": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.1", + "once": "1.4.0" } }, "pumpify": { "version": "1.5.1", "bundled": true, "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" + "duplexify": "3.6.0", + "inherits": "2.0.3", + "pump": "2.0.1" }, "dependencies": { "pump": { "version": "2.0.1", "bundled": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.1", + "once": "1.4.0" } } } @@ -10467,8 +10467,8 @@ "version": "6.1.0", "bundled": true, "requires": { - "decode-uri-component": "^0.2.0", - "strict-uri-encode": "^2.0.0" + "decode-uri-component": "0.2.0", + "strict-uri-encode": "2.0.0" } }, "qw": { @@ -10479,10 +10479,10 @@ "version": "1.2.7", "bundled": true, "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" }, "dependencies": { "minimist": { @@ -10495,113 +10495,113 @@ "version": "1.0.7", "bundled": true, "requires": { - "mute-stream": "~0.0.4" + "mute-stream": "0.0.7" } }, "read-cmd-shim": { "version": "1.0.1", "bundled": true, "requires": { - "graceful-fs": "^4.1.2" + "graceful-fs": "4.1.11" } }, "read-installed": { "version": "4.0.3", "bundled": true, "requires": { - "debuglog": "^1.0.1", - "graceful-fs": "^4.1.2", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "slide": "~1.1.3", - "util-extend": "^1.0.1" + "debuglog": "1.0.1", + "graceful-fs": "4.1.11", + "read-package-json": "2.0.13", + "readdir-scoped-modules": "1.0.2", + "semver": "5.5.0", + "slide": "1.1.6", + "util-extend": "1.0.3" } }, "read-package-json": { "version": "2.0.13", "bundled": true, "requires": { - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-better-errors": "^1.0.1", - "normalize-package-data": "^2.0.0", - "slash": "^1.0.0" + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "json-parse-better-errors": "1.0.2", + "normalize-package-data": "2.4.0", + "slash": "1.0.0" } }, "read-package-tree": { "version": "5.2.1", "bundled": true, "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "once": "^1.3.0", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0" + "debuglog": "1.0.1", + "dezalgo": "1.0.3", + "once": "1.4.0", + "read-package-json": "2.0.13", + "readdir-scoped-modules": "1.0.2" } }, "readable-stream": { "version": "2.3.6", "bundled": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "readdir-scoped-modules": { "version": "1.0.2", "bundled": true, "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" + "debuglog": "1.0.1", + "dezalgo": "1.0.3", + "graceful-fs": "4.1.11", + "once": "1.4.0" } }, "registry-auth-token": { "version": "3.3.2", "bundled": true, "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" + "rc": "1.2.7", + "safe-buffer": "5.1.2" } }, "registry-url": { "version": "3.1.0", "bundled": true, "requires": { - "rc": "^1.0.1" + "rc": "1.2.7" } }, "request": { "version": "2.88.0", "bundled": true, "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" + "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" } }, "require-directory": { @@ -10624,14 +10624,14 @@ "version": "2.6.2", "bundled": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" } }, "run-queue": { "version": "1.0.3", "bundled": true, "requires": { - "aproba": "^1.1.1" + "aproba": "1.2.0" } }, "safe-buffer": { @@ -10650,7 +10650,7 @@ "version": "2.1.0", "bundled": true, "requires": { - "semver": "^5.0.3" + "semver": "5.5.0" } }, "set-blocking": { @@ -10661,15 +10661,15 @@ "version": "2.0.1", "bundled": true, "requires": { - "graceful-fs": "^4.1.2", - "readable-stream": "^2.0.2" + "graceful-fs": "4.1.11", + "readable-stream": "2.3.6" } }, "shebang-command": { "version": "1.2.0", "bundled": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "1.0.0" } }, "shebang-regex": { @@ -10696,16 +10696,16 @@ "version": "2.2.0", "bundled": true, "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.0.1" + "ip": "1.1.5", + "smart-buffer": "4.0.1" } }, "socks-proxy-agent": { "version": "4.0.1", "bundled": true, "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" + "agent-base": "4.2.0", + "socks": "2.2.0" } }, "sorted-object": { @@ -10716,16 +10716,16 @@ "version": "2.1.3", "bundled": true, "requires": { - "from2": "^1.3.0", - "stream-iterate": "^1.1.0" + "from2": "1.3.0", + "stream-iterate": "1.2.0" }, "dependencies": { "from2": { "version": "1.3.0", "bundled": true, "requires": { - "inherits": "~2.0.1", - "readable-stream": "~1.1.10" + "inherits": "2.0.3", + "readable-stream": "1.1.14" } }, "isarray": { @@ -10736,10 +10736,10 @@ "version": "1.1.14", "bundled": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "string_decoder": { @@ -10752,8 +10752,8 @@ "version": "3.0.0", "bundled": true, "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" } }, "spdx-exceptions": { @@ -10764,8 +10764,8 @@ "version": "3.0.0", "bundled": true, "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" } }, "spdx-license-ids": { @@ -10776,15 +10776,15 @@ "version": "1.14.2", "bundled": true, "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" + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" } }, "ssri": { @@ -10795,16 +10795,16 @@ "version": "1.2.2", "bundled": true, "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" + "end-of-stream": "1.4.1", + "stream-shift": "1.0.0" } }, "stream-iterate": { "version": "1.2.0", "bundled": true, "requires": { - "readable-stream": "^2.1.5", - "stream-shift": "^1.0.0" + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" } }, "stream-shift": { @@ -10819,8 +10819,8 @@ "version": "2.1.1", "bundled": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { "ansi-regex": { @@ -10835,7 +10835,7 @@ "version": "4.0.0", "bundled": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -10844,7 +10844,7 @@ "version": "1.1.1", "bundled": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "stringify-package": { @@ -10855,7 +10855,7 @@ "version": "3.0.1", "bundled": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-eof": { @@ -10870,20 +10870,20 @@ "version": "5.4.0", "bundled": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } }, "tar": { "version": "4.4.6", "bundled": true, "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.3", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.3", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.2" }, "dependencies": { "yallist": { @@ -10896,7 +10896,7 @@ "version": "1.2.0", "bundled": true, "requires": { - "execa": "^0.7.0" + "execa": "0.7.0" } }, "text-table": { @@ -10911,8 +10911,8 @@ "version": "2.0.3", "bundled": true, "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" + "readable-stream": "2.3.6", + "xtend": "4.0.1" } }, "timed-out": { @@ -10927,15 +10927,15 @@ "version": "2.4.3", "bundled": true, "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "psl": "1.1.29", + "punycode": "1.4.1" } }, "tunnel-agent": { "version": "0.6.0", "bundled": true, "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "tweetnacl": { @@ -10959,21 +10959,21 @@ "version": "1.1.0", "bundled": true, "requires": { - "unique-slug": "^2.0.0" + "unique-slug": "2.0.0" } }, "unique-slug": { "version": "2.0.0", "bundled": true, "requires": { - "imurmurhash": "^0.1.4" + "imurmurhash": "0.1.4" } }, "unique-string": { "version": "1.0.0", "bundled": true, "requires": { - "crypto-random-string": "^1.0.0" + "crypto-random-string": "1.0.0" } }, "unpipe": { @@ -10988,23 +10988,23 @@ "version": "2.5.0", "bundled": true, "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" + "boxen": "1.3.0", + "chalk": "2.4.1", + "configstore": "3.1.2", + "import-lazy": "2.1.0", + "is-ci": "1.1.0", + "is-installed-globally": "0.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" } }, "url-parse-lax": { "version": "1.0.0", "bundled": true, "requires": { - "prepend-http": "^1.0.1" + "prepend-http": "1.0.4" } }, "util-deprecate": { @@ -11023,38 +11023,38 @@ "version": "3.0.4", "bundled": true, "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" } }, "validate-npm-package-name": { "version": "3.0.0", "bundled": true, "requires": { - "builtins": "^1.0.3" + "builtins": "1.0.3" } }, "verror": { "version": "1.10.0", "bundled": true, "requires": { - "assert-plus": "^1.0.0", + "assert-plus": "1.0.0", "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "extsprintf": "1.3.0" } }, "wcwidth": { "version": "1.0.1", "bundled": true, "requires": { - "defaults": "^1.0.3" + "defaults": "1.0.3" } }, "which": { "version": "1.3.1", "bundled": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } }, "which-module": { @@ -11065,16 +11065,16 @@ "version": "1.1.2", "bundled": true, "requires": { - "string-width": "^1.0.2" + "string-width": "1.0.2" }, "dependencies": { "string-width": { "version": "1.0.2", "bundled": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } } } @@ -11083,31 +11083,31 @@ "version": "2.0.0", "bundled": true, "requires": { - "string-width": "^2.1.1" + "string-width": "2.1.1" } }, "worker-farm": { "version": "1.6.0", "bundled": true, "requires": { - "errno": "~0.1.7" + "errno": "0.1.7" } }, "wrap-ansi": { "version": "2.1.0", "bundled": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "string-width": "1.0.2", + "strip-ansi": "3.0.1" }, "dependencies": { "string-width": { "version": "1.0.2", "bundled": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } } } @@ -11120,9 +11120,9 @@ "version": "2.3.0", "bundled": true, "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" } }, "xdg-basedir": { @@ -11145,18 +11145,18 @@ "version": "11.0.0", "bundled": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.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", - "yargs-parser": "^9.0.2" + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" }, "dependencies": { "y18n": { @@ -11169,7 +11169,7 @@ "version": "9.0.2", "bundled": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "4.1.0" } } } @@ -11180,8 +11180,8 @@ "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", "dev": true, "requires": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" + "config-chain": "1.1.12", + "pify": "3.0.0" } }, "npm-run-path": { @@ -11190,7 +11190,7 @@ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "^2.0.0" + "path-key": "2.0.1" } }, "nth-check": { @@ -11199,7 +11199,7 @@ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "dev": true, "requires": { - "boolbase": "~1.0.0" + "boolbase": "1.0.0" } }, "num2fraction": { @@ -11238,9 +11238,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { "define-property": { @@ -11249,7 +11249,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "kind-of": { @@ -11258,7 +11258,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -11275,7 +11275,7 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "^3.0.0" + "isobject": "3.0.1" } }, "object.defaults": { @@ -11284,10 +11284,10 @@ "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" } }, "object.getownpropertydescriptors": { @@ -11296,8 +11296,8 @@ "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" + "define-properties": "1.1.3", + "es-abstract": "1.12.0" } }, "object.map": { @@ -11306,8 +11306,8 @@ "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "for-own": "1.0.0", + "make-iterator": "1.0.1" } }, "object.omit": { @@ -11316,8 +11316,8 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" + "for-own": "0.1.5", + "is-extendable": "0.1.1" }, "dependencies": { "for-own": { @@ -11326,7 +11326,7 @@ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "^1.0.1" + "for-in": "1.0.2" } } } @@ -11337,7 +11337,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "object.values": { @@ -11346,10 +11346,10 @@ "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.6.1", - "function-bind": "^1.1.0", - "has": "^1.0.1" + "define-properties": "1.1.3", + "es-abstract": "1.12.0", + "function-bind": "1.1.1", + "has": "1.0.3" } }, "on-finished": { @@ -11367,7 +11367,7 @@ "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "onetime": { @@ -11376,7 +11376,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "1.2.0" } }, "opn": { @@ -11385,7 +11385,7 @@ "integrity": "sha512-Jd/GpzPyHF4P2/aNOVmS3lfMSWV9J7cOhCG1s08XCEAsPkB7lp6ddiU0J7XzyQRDUh8BqJ7PchfINjR8jyofRQ==", "dev": true, "requires": { - "is-wsl": "^1.1.0" + "is-wsl": "1.1.0" } }, "optimist": { @@ -11394,8 +11394,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "minimist": "0.0.10", + "wordwrap": "0.0.3" }, "dependencies": { "minimist": { @@ -11418,12 +11418,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "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" + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" } }, "optipng-bin": { @@ -11433,9 +11433,9 @@ "dev": true, "optional": true, "requires": { - "bin-build": "^3.0.0", - "bin-wrapper": "^4.0.0", - "logalot": "^2.0.0" + "bin-build": "3.0.0", + "bin-wrapper": "4.1.0", + "logalot": "2.1.0" } }, "orchestrator": { @@ -11444,9 +11444,9 @@ "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", "dev": true, "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.1" } }, "ordered-read-streams": { @@ -11462,7 +11462,7 @@ "dev": true, "optional": true, "requires": { - "arch": "^2.1.0" + "arch": "2.1.1" } }, "os-homedir": { @@ -11491,7 +11491,7 @@ "dev": true, "optional": true, "requires": { - "p-timeout": "^1.1.1" + "p-timeout": "1.2.1" } }, "p-finally": { @@ -11514,7 +11514,7 @@ "dev": true, "optional": true, "requires": { - "p-reduce": "^1.0.0" + "p-reduce": "1.0.0" } }, "p-pipe": { @@ -11536,7 +11536,7 @@ "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", "dev": true, "requires": { - "p-finally": "^1.0.0" + "p-finally": "1.0.0" } }, "parse-filepath": { @@ -11545,9 +11545,9 @@ "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" } }, "parse-glob": { @@ -11556,10 +11556,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" }, "dependencies": { "is-extglob": { @@ -11574,7 +11574,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } } } @@ -11585,8 +11585,8 @@ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "error-ex": "1.3.2", + "json-parse-better-errors": "1.0.2" } }, "parse-node-version": { @@ -11607,7 +11607,7 @@ "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "dev": true, "requires": { - "better-assert": "~1.0.0" + "better-assert": "1.0.2" } }, "parseuri": { @@ -11616,7 +11616,7 @@ "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", "dev": true, "requires": { - "better-assert": "~1.0.0" + "better-assert": "1.0.2" } }, "parseurl": { @@ -11649,7 +11649,7 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "pinkie-promise": "2.0.1" } }, "path-is-absolute": { @@ -11682,7 +11682,7 @@ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { - "path-root-regex": "^0.1.0" + "path-root-regex": "0.1.2" } }, "path-root-regex": { @@ -11697,7 +11697,7 @@ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" } }, "pause-stream": { @@ -11706,7 +11706,7 @@ "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { - "through": "~2.3" + "through": "2.3.8" } }, "pend": { @@ -11727,15 +11727,15 @@ "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", "dev": true, "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" + "es6-promise": "4.2.5", + "extract-zip": "1.6.7", + "fs-extra": "1.0.0", + "hasha": "2.2.0", + "kew": "0.7.0", + "progress": "1.1.8", + "request": "2.88.0", + "request-progress": "2.0.1", + "which": "1.3.1" }, "dependencies": { "es6-promise": { @@ -11770,7 +11770,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "^2.0.0" + "pinkie": "2.0.4" } }, "plugin-error": { @@ -11779,10 +11779,10 @@ "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", "dev": true, "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" + "ansi-colors": "1.1.0", + "arr-diff": "4.0.0", + "arr-union": "3.1.0", + "extend-shallow": "3.0.2" } }, "plugin-log": { @@ -11791,8 +11791,8 @@ "integrity": "sha1-hgSc9qsQgzOYqTHzaJy67nteEzM=", "dev": true, "requires": { - "chalk": "^1.1.1", - "dateformat": "^1.0.11" + "chalk": "1.1.3", + "dateformat": "1.0.12" }, "dependencies": { "ansi-styles": { @@ -11807,11 +11807,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "dateformat": { @@ -11820,8 +11820,8 @@ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", "dev": true, "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" + "get-stdin": "4.0.1", + "meow": "3.7.0" } }, "supports-color": { @@ -11838,7 +11838,7 @@ "integrity": "sha512-lJl0ojUynAM1BZn58Pas2WT/TXeC1+bS+UqShl0x9+49AtOn7DixRXVzaC8qrDOIxNDmepKnLuMTH7NQmkX0PA==", "dev": true, "requires": { - "irregular-plurals": "^2.0.0" + "irregular-plurals": "2.0.0" } }, "pluralize": { @@ -11859,9 +11859,9 @@ "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", "dev": true, "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "chalk": "2.4.1", + "source-map": "0.6.1", + "supports-color": "5.5.0" }, "dependencies": { "source-map": { @@ -11878,10 +11878,10 @@ "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==", "dev": true, "requires": { - "css-unit-converter": "^1.1.1", - "postcss": "^7.0.5", - "postcss-selector-parser": "^5.0.0-rc.4", - "postcss-value-parser": "^3.3.1" + "css-unit-converter": "1.1.1", + "postcss": "7.0.6", + "postcss-selector-parser": "5.0.0-rc.4", + "postcss-value-parser": "3.3.1" } }, "postcss-colormin": { @@ -11890,11 +11890,11 @@ "integrity": "sha512-1QJc2coIehnVFsz0otges8kQLsryi4lo19WD+U5xCWvXd0uw/Z+KKYnbiNDCnO9GP+PvErPHCG0jNvWTngk9Rw==", "dev": true, "requires": { - "browserslist": "^4.0.0", - "color": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "browserslist": "4.3.5", + "color": "3.1.0", + "has": "1.0.3", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-convert-values": { @@ -11903,8 +11903,8 @@ "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", "dev": true, "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-discard-comments": { @@ -11913,7 +11913,7 @@ "integrity": "sha512-Ay+rZu1Sz6g8IdzRjUgG2NafSNpp2MSMOQUb+9kkzzzP+kh07fP0yNbhtFejURnyVXSX3FYy2nVNW1QTnNjgBQ==", "dev": true, "requires": { - "postcss": "^7.0.0" + "postcss": "7.0.6" } }, "postcss-discard-duplicates": { @@ -11922,7 +11922,7 @@ "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", "dev": true, "requires": { - "postcss": "^7.0.0" + "postcss": "7.0.6" } }, "postcss-discard-empty": { @@ -11931,7 +11931,7 @@ "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", "dev": true, "requires": { - "postcss": "^7.0.0" + "postcss": "7.0.6" } }, "postcss-discard-overridden": { @@ -11940,7 +11940,7 @@ "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", "dev": true, "requires": { - "postcss": "^7.0.0" + "postcss": "7.0.6" } }, "postcss-load-config": { @@ -11949,8 +11949,8 @@ "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", "dev": true, "requires": { - "cosmiconfig": "^4.0.0", - "import-cwd": "^2.0.0" + "cosmiconfig": "4.0.0", + "import-cwd": "2.1.0" }, "dependencies": { "cosmiconfig": { @@ -11959,10 +11959,10 @@ "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", "dev": true, "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "parse-json": "^4.0.0", - "require-from-string": "^2.0.1" + "is-directory": "0.3.1", + "js-yaml": "3.12.0", + "parse-json": "4.0.0", + "require-from-string": "2.0.2" } } } @@ -11974,9 +11974,9 @@ "dev": true, "requires": { "css-color-names": "0.0.4", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "stylehacks": "^4.0.0" + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1", + "stylehacks": "4.0.1" } }, "postcss-merge-rules": { @@ -11985,12 +11985,12 @@ "integrity": "sha512-UiuXwCCJtQy9tAIxsnurfF0mrNHKc4NnNx6NxqmzNNjXpQwLSukUxELHTRF0Rg1pAmcoKLih8PwvZbiordchag==", "dev": true, "requires": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "cssnano-util-same-parent": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0", - "vendors": "^1.0.0" + "browserslist": "4.3.5", + "caniuse-api": "3.0.0", + "cssnano-util-same-parent": "4.0.1", + "postcss": "7.0.6", + "postcss-selector-parser": "3.1.1", + "vendors": "1.0.2" }, "dependencies": { "postcss-selector-parser": { @@ -11999,9 +11999,9 @@ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "dev": true, "requires": { - "dot-prop": "^4.1.1", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "dot-prop": "4.2.0", + "indexes-of": "1.0.1", + "uniq": "1.0.1" } } } @@ -12012,8 +12012,8 @@ "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", "dev": true, "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-minify-gradients": { @@ -12022,10 +12022,10 @@ "integrity": "sha512-pySEW3E6Ly5mHm18rekbWiAjVi/Wj8KKt2vwSfVFAWdW6wOIekgqxKxLU7vJfb107o3FDNPkaYFCxGAJBFyogA==", "dev": true, "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "is-color-stop": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "cssnano-util-get-arguments": "4.0.0", + "is-color-stop": "1.1.0", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-minify-params": { @@ -12034,12 +12034,12 @@ "integrity": "sha512-h4W0FEMEzBLxpxIVelRtMheskOKKp52ND6rJv+nBS33G1twu2tCyurYj/YtgU76+UDCvWeNs0hs8HFAWE2OUFg==", "dev": true, "requires": { - "alphanum-sort": "^1.0.0", - "browserslist": "^4.0.0", - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "uniqs": "^2.0.0" + "alphanum-sort": "1.0.2", + "browserslist": "4.3.5", + "cssnano-util-get-arguments": "4.0.0", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1", + "uniqs": "2.0.0" } }, "postcss-minify-selectors": { @@ -12048,10 +12048,10 @@ "integrity": "sha512-8+plQkomve3G+CodLCgbhAKrb5lekAnLYuL1d7Nz+/7RANpBEVdgBkPNwljfSKvZ9xkkZTZITd04KP+zeJTJqg==", "dev": true, "requires": { - "alphanum-sort": "^1.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" + "alphanum-sort": "1.0.2", + "has": "1.0.3", + "postcss": "7.0.6", + "postcss-selector-parser": "3.1.1" }, "dependencies": { "postcss-selector-parser": { @@ -12060,9 +12060,9 @@ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "dev": true, "requires": { - "dot-prop": "^4.1.1", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "dot-prop": "4.2.0", + "indexes-of": "1.0.1", + "uniq": "1.0.1" } } } @@ -12073,7 +12073,7 @@ "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", "dev": true, "requires": { - "postcss": "^7.0.0" + "postcss": "7.0.6" } }, "postcss-normalize-display-values": { @@ -12082,9 +12082,9 @@ "integrity": "sha512-R5mC4vaDdvsrku96yXP7zak+O3Mm9Y8IslUobk7IMP+u/g+lXvcN4jngmHY5zeJnrQvE13dfAg5ViU05ZFDwdg==", "dev": true, "requires": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "cssnano-util-get-match": "4.0.0", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-normalize-positions": { @@ -12093,10 +12093,10 @@ "integrity": "sha512-GNoOaLRBM0gvH+ZRb2vKCIujzz4aclli64MBwDuYGU2EY53LwiP7MxOZGE46UGtotrSnmarPPZ69l2S/uxdaWA==", "dev": true, "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "cssnano-util-get-arguments": "4.0.0", + "has": "1.0.3", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-normalize-repeat-style": { @@ -12105,10 +12105,10 @@ "integrity": "sha512-fFHPGIjBUyUiswY2rd9rsFcC0t3oRta4wxE1h3lpwfQZwFeFjXFSiDtdJ7APCmHQOnUZnqYBADNRPKPwFAONgA==", "dev": true, "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "cssnano-util-get-arguments": "4.0.0", + "cssnano-util-get-match": "4.0.0", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-normalize-string": { @@ -12117,9 +12117,9 @@ "integrity": "sha512-IJoexFTkAvAq5UZVxWXAGE0yLoNN/012v7TQh5nDo6imZJl2Fwgbhy3J2qnIoaDBrtUP0H7JrXlX1jjn2YcvCQ==", "dev": true, "requires": { - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "has": "1.0.3", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-normalize-timing-functions": { @@ -12128,9 +12128,9 @@ "integrity": "sha512-1nOtk7ze36+63ONWD8RCaRDYsnzorrj+Q6fxkQV+mlY5+471Qx9kspqv0O/qQNMeApg8KNrRf496zHwJ3tBZ7w==", "dev": true, "requires": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "cssnano-util-get-match": "4.0.0", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-normalize-unicode": { @@ -12139,9 +12139,9 @@ "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", "dev": true, "requires": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "browserslist": "4.3.5", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-normalize-url": { @@ -12150,10 +12150,10 @@ "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", "dev": true, "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "is-absolute-url": "2.1.0", + "normalize-url": "3.3.0", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-normalize-whitespace": { @@ -12162,8 +12162,8 @@ "integrity": "sha512-U8MBODMB2L+nStzOk6VvWWjZgi5kQNShCyjRhMT3s+W9Jw93yIjOnrEkKYD3Ul7ChWbEcjDWmXq0qOL9MIAnAw==", "dev": true, "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-ordered-values": { @@ -12172,9 +12172,9 @@ "integrity": "sha512-PeJiLgJWPzkVF8JuKSBcylaU+hDJ/TX3zqAMIjlghgn1JBi6QwQaDZoDIlqWRcCAI8SxKrt3FCPSRmOgKRB97Q==", "dev": true, "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "cssnano-util-get-arguments": "4.0.0", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-reduce-initial": { @@ -12183,10 +12183,10 @@ "integrity": "sha512-epUiC39NonKUKG+P3eAOKKZtm5OtAtQJL7Ye0CBN1f+UQTHzqotudp+hki7zxXm7tT0ZAKDMBj1uihpPjP25ug==", "dev": true, "requires": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0" + "browserslist": "4.3.5", + "caniuse-api": "3.0.0", + "has": "1.0.3", + "postcss": "7.0.6" } }, "postcss-reduce-transforms": { @@ -12195,10 +12195,10 @@ "integrity": "sha512-sZVr3QlGs0pjh6JAIe6DzWvBaqYw05V1t3d9Tp+VnFRT5j+rsqoWsysh/iSD7YNsULjq9IAylCznIwVd5oU/zA==", "dev": true, "requires": { - "cssnano-util-get-match": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "cssnano-util-get-match": "4.0.0", + "has": "1.0.3", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1" } }, "postcss-selector-parser": { @@ -12207,9 +12207,9 @@ "integrity": "sha512-0XvfYuShrKlTk1ooUrVzMCFQRcypsdEIsGqh5IxC5rdtBi4/M/tDAJeSONwC2MTqEFsmPZYAV7Dd4X8rgAfV0A==", "dev": true, "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "cssesc": "2.0.0", + "indexes-of": "1.0.1", + "uniq": "1.0.1" } }, "postcss-svgo": { @@ -12218,10 +12218,10 @@ "integrity": "sha512-YD5uIk5NDRySy0hcI+ZJHwqemv2WiqqzDgtvgMzO8EGSkK5aONyX8HMVFRFJSdO8wUWTuisUFn/d7yRRbBr5Qw==", "dev": true, "requires": { - "is-svg": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "svgo": "^1.0.0" + "is-svg": "3.0.0", + "postcss": "7.0.6", + "postcss-value-parser": "3.3.1", + "svgo": "1.1.1" } }, "postcss-unique-selectors": { @@ -12230,9 +12230,9 @@ "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", "dev": true, "requires": { - "alphanum-sort": "^1.0.0", - "postcss": "^7.0.0", - "uniqs": "^2.0.0" + "alphanum-sort": "1.0.2", + "postcss": "7.0.6", + "uniqs": "2.0.0" } }, "postcss-value-parser": { @@ -12297,7 +12297,7 @@ "dev": true, "optional": true, "requires": { - "asap": "~2.0.3" + "asap": "2.0.6" } }, "proto-list": { @@ -12331,8 +12331,8 @@ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.1", + "once": "1.3.3" }, "dependencies": { "end-of-stream": { @@ -12341,7 +12341,7 @@ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { - "once": "^1.4.0" + "once": "1.4.0" }, "dependencies": { "once": { @@ -12350,7 +12350,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } } } @@ -12388,9 +12388,9 @@ "dev": true, "optional": true, "requires": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" + "decode-uri-component": "0.2.0", + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" }, "dependencies": { "object-assign": { @@ -12408,9 +12408,9 @@ "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dev": true, "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" }, "dependencies": { "is-number": { @@ -12433,8 +12433,8 @@ "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, "requires": { - "bytes": "1", - "string_decoder": "0.10" + "bytes": "1.0.0", + "string_decoder": "0.10.31" } }, "read-pkg": { @@ -12443,9 +12443,9 @@ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" }, "dependencies": { "graceful-fs": { @@ -12460,9 +12460,9 @@ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "graceful-fs": "4.1.15", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" } }, "pify": { @@ -12479,8 +12479,8 @@ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "find-up": "1.1.2", + "read-pkg": "1.1.0" } }, "readable-stream": { @@ -12489,10 +12489,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "readdirp": { @@ -12501,9 +12501,9 @@ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "graceful-fs": "4.1.15", + "micromatch": "3.1.10", + "readable-stream": "2.3.6" }, "dependencies": { "graceful-fs": { @@ -12524,13 +12524,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -12539,7 +12539,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -12550,7 +12550,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "^1.1.6" + "resolve": "1.8.1" } }, "redent": { @@ -12559,8 +12559,8 @@ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" + "indent-string": "2.1.0", + "strip-indent": "1.0.1" } }, "regenerate": { @@ -12575,7 +12575,7 @@ "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", "dev": true, "requires": { - "regenerate": "^1.4.0" + "regenerate": "1.4.0" } }, "regenerator-transform": { @@ -12584,7 +12584,7 @@ "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", "dev": true, "requires": { - "private": "^0.1.6" + "private": "0.1.8" } }, "regex-cache": { @@ -12593,7 +12593,7 @@ "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, "requires": { - "is-equal-shallow": "^0.1.3" + "is-equal-shallow": "0.1.3" } }, "regex-not": { @@ -12602,8 +12602,8 @@ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" } }, "regexpp": { @@ -12618,12 +12618,12 @@ "integrity": "sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw==", "dev": true, "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", - "regjsgen": "^0.4.0", - "regjsparser": "^0.3.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" + "regenerate": "1.4.0", + "regenerate-unicode-properties": "7.0.0", + "regjsgen": "0.4.0", + "regjsparser": "0.3.0", + "unicode-match-property-ecmascript": "1.0.4", + "unicode-match-property-value-ecmascript": "1.0.2" } }, "regjsgen": { @@ -12638,7 +12638,7 @@ "integrity": "sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA==", "dev": true, "requires": { - "jsesc": "~0.5.0" + "jsesc": "0.5.0" }, "dependencies": { "jsesc": { @@ -12673,7 +12673,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "^1.0.0" + "is-finite": "1.0.2" } }, "replace-ext": { @@ -12688,26 +12688,26 @@ "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "dev": true, "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" + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.7", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.3", + "har-validator": "5.1.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.21", + "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": { "qs": { @@ -12724,7 +12724,7 @@ "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", "dev": true, "requires": { - "throttleit": "^1.0.0" + "throttleit": "1.0.0" } }, "require-from-string": { @@ -12739,8 +12739,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" + "caller-path": "0.1.0", + "resolve-from": "1.0.1" }, "dependencies": { "caller-path": { @@ -12749,7 +12749,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "^0.2.0" + "callsites": "0.2.0" } }, "callsites": { @@ -12778,7 +12778,7 @@ "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "1.0.6" } }, "resolve-dir": { @@ -12787,8 +12787,8 @@ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" } }, "resolve-from": { @@ -12810,7 +12810,7 @@ "dev": true, "optional": true, "requires": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "1.0.1" } }, "restore-cursor": { @@ -12819,8 +12819,8 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "onetime": "2.0.1", + "signal-exit": "3.0.2" } }, "ret": { @@ -12853,7 +12853,7 @@ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "align-text": "^0.1.1" + "align-text": "0.1.4" } }, "rimraf": { @@ -12862,7 +12862,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.3" }, "dependencies": { "glob": { @@ -12871,12 +12871,12 @@ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": 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" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" } }, "minimatch": { @@ -12885,7 +12885,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } } } @@ -12896,7 +12896,7 @@ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "is-promise": "^2.1.0" + "is-promise": "2.1.0" } }, "run-sequence": { @@ -12905,9 +12905,9 @@ "integrity": "sha512-qkzZnQWMZjcKbh3CNly2srtrkaO/2H/SI5f2eliMCapdRD3UhMrwjfOAZJAnZ2H8Ju4aBzFZkBGXUqFs9V0yxw==", "dev": true, "requires": { - "chalk": "^1.1.3", - "fancy-log": "^1.3.2", - "plugin-error": "^0.1.2" + "chalk": "1.1.3", + "fancy-log": "1.3.3", + "plugin-error": "0.1.2" }, "dependencies": { "ansi-styles": { @@ -12922,8 +12922,8 @@ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" } }, "arr-union": { @@ -12944,11 +12944,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "extend-shallow": { @@ -12957,7 +12957,7 @@ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "dev": true, "requires": { - "kind-of": "^1.1.0" + "kind-of": "1.1.0" } }, "kind-of": { @@ -12972,11 +12972,11 @@ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" } }, "supports-color": { @@ -12993,7 +12993,7 @@ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "requires": { - "tslib": "^1.9.0" + "tslib": "1.9.3" } }, "safe-buffer": { @@ -13014,7 +13014,7 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "~0.1.10" + "ret": "0.1.15" } }, "safer-buffer": { @@ -13035,7 +13035,7 @@ "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", "dev": true, "requires": { - "commander": "~2.8.1" + "commander": "2.8.1" } }, "select": { @@ -13063,7 +13063,7 @@ "dev": true, "optional": true, "requires": { - "semver": "^5.3.0" + "semver": "5.6.0" } }, "send": { @@ -13073,18 +13073,18 @@ "dev": true, "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", + "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", + "http-errors": "1.6.3", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.4.0" }, "dependencies": { "debug": { @@ -13122,13 +13122,13 @@ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, "requires": { - "accepts": "~1.3.4", + "accepts": "1.3.5", "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" + "escape-html": "1.0.3", + "http-errors": "1.6.3", + "mime-types": "2.1.21", + "parseurl": "1.3.2" }, "dependencies": { "debug": { @@ -13154,9 +13154,9 @@ "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", "send": "0.16.2" } }, @@ -13166,10 +13166,10 @@ "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" }, "dependencies": { "extend-shallow": { @@ -13178,7 +13178,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -13195,7 +13195,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "1.0.0" } }, "shebang-regex": { @@ -13221,7 +13221,7 @@ "resolved": "https://registry.npmjs.org/signalr/-/signalr-2.4.0.tgz", "integrity": "sha512-GPJHb3pcNk3IUui5/WG8lMuarEn+Vpc8wEvJ60w0KQ43W9FHnJcuNcF8dkZePr81eBslzicsRdyEunKNF7KjZQ==", "requires": { - "jquery": ">=1.6.4" + "jquery": "3.3.1" } }, "simple-swizzle": { @@ -13230,7 +13230,7 @@ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "dev": true, "requires": { - "is-arrayish": "^0.3.1" + "is-arrayish": "0.3.2" }, "dependencies": { "is-arrayish": { @@ -13253,9 +13253,9 @@ "integrity": "sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" + "ansi-styles": "3.2.1", + "astral-regex": "1.0.0", + "is-fullwidth-code-point": "2.0.0" } }, "snapdragon": { @@ -13264,14 +13264,14 @@ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "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" + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" }, "dependencies": { "debug": { @@ -13289,7 +13289,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -13298,7 +13298,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "ms": { @@ -13315,9 +13315,9 @@ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" }, "dependencies": { "define-property": { @@ -13326,7 +13326,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "is-accessor-descriptor": { @@ -13335,7 +13335,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -13344,7 +13344,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -13353,9 +13353,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -13366,7 +13366,7 @@ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "kind-of": "^3.2.0" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -13375,7 +13375,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -13386,12 +13386,12 @@ "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", + "debug": "3.1.0", + "engine.io": "3.2.1", + "has-binary2": "1.0.3", + "socket.io-adapter": "1.1.1", "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" + "socket.io-parser": "3.2.0" }, "dependencies": { "debug": { @@ -13427,15 +13427,15 @@ "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", + "debug": "3.1.0", + "engine.io-client": "3.2.1", + "has-binary2": "1.0.3", "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", + "socket.io-parser": "3.2.0", "to-array": "0.1.4" }, "dependencies": { @@ -13463,7 +13463,7 @@ "dev": true, "requires": { "component-emitter": "1.2.1", - "debug": "~3.1.0", + "debug": "3.1.0", "isarray": "2.0.1" }, "dependencies": { @@ -13496,7 +13496,7 @@ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", "dev": true, "requires": { - "is-plain-obj": "^1.0.0" + "is-plain-obj": "1.1.0" } }, "sort-keys-length": { @@ -13505,7 +13505,7 @@ "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", "dev": true, "requires": { - "sort-keys": "^1.0.0" + "sort-keys": "1.1.2" } }, "source-map": { @@ -13520,11 +13520,11 @@ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "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" + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" } }, "source-map-url": { @@ -13545,8 +13545,8 @@ "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", "dev": true, "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.2" } }, "spdx-exceptions": { @@ -13561,8 +13561,8 @@ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "spdx-exceptions": "2.2.0", + "spdx-license-ids": "3.0.2" } }, "spdx-license-ids": { @@ -13582,7 +13582,7 @@ "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "requires": { - "through": "2" + "through": "2.3.8" } }, "split-string": { @@ -13591,7 +13591,7 @@ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { - "extend-shallow": "^3.0.0" + "extend-shallow": "3.0.2" } }, "sprintf-js": { @@ -13607,9 +13607,9 @@ "dev": true, "optional": true, "requires": { - "chalk": "^1.0.0", - "console-stream": "^0.1.1", - "lpad-align": "^1.0.1" + "chalk": "1.1.3", + "console-stream": "0.1.1", + "lpad-align": "1.1.2" }, "dependencies": { "ansi-styles": { @@ -13626,11 +13626,11 @@ "dev": true, "optional": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "supports-color": { @@ -13648,15 +13648,15 @@ "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", "dev": true, "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" + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" } }, "stable": { @@ -13671,8 +13671,8 @@ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "define-property": "0.2.5", + "object-copy": "0.1.0" }, "dependencies": { "define-property": { @@ -13681,7 +13681,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } } } @@ -13698,8 +13698,8 @@ "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", "dev": true, "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" + "duplexer": "0.1.1", + "through": "2.3.8" } }, "stream-consume": { @@ -13714,10 +13714,10 @@ "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "date-format": "1.2.0", + "debug": "3.2.6", + "mkdirp": "0.5.1", + "readable-stream": "2.3.6" }, "dependencies": { "debug": { @@ -13726,7 +13726,7 @@ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "isarray": { @@ -13741,13 +13741,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -13756,7 +13756,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -13780,8 +13780,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { "ansi-regex": { @@ -13796,7 +13796,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -13813,7 +13813,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-bom": { @@ -13822,8 +13822,8 @@ "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", "dev": true, "requires": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" } }, "strip-bom-stream": { @@ -13832,8 +13832,8 @@ "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", "dev": true, "requires": { - "first-chunk-stream": "^2.0.0", - "strip-bom": "^2.0.0" + "first-chunk-stream": "2.0.0", + "strip-bom": "2.0.0" }, "dependencies": { "first-chunk-stream": { @@ -13842,7 +13842,7 @@ "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", "dev": true, "requires": { - "readable-stream": "^2.0.2" + "readable-stream": "2.3.6" } }, "isarray": { @@ -13857,13 +13857,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -13872,7 +13872,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "strip-bom": { @@ -13881,7 +13881,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } } } @@ -13892,7 +13892,7 @@ "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", "dev": true, "requires": { - "is-natural-number": "^4.0.1" + "is-natural-number": "4.0.1" } }, "strip-eof": { @@ -13907,7 +13907,7 @@ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "get-stdin": "^4.0.1" + "get-stdin": "4.0.1" } }, "strip-json-comments": { @@ -13922,7 +13922,7 @@ "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", "dev": true, "requires": { - "escape-string-regexp": "^1.0.2" + "escape-string-regexp": "1.0.5" } }, "stylehacks": { @@ -13931,9 +13931,9 @@ "integrity": "sha512-TK5zEPeD9NyC1uPIdjikzsgWxdQQN/ry1X3d1iOz1UkYDCmcr928gWD1KHgyC27F50UnE0xCTrBOO1l6KR8M4w==", "dev": true, "requires": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" + "browserslist": "4.3.5", + "postcss": "7.0.6", + "postcss-selector-parser": "3.1.1" }, "dependencies": { "postcss-selector-parser": { @@ -13942,9 +13942,9 @@ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "dev": true, "requires": { - "dot-prop": "^4.1.1", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "dot-prop": "4.2.0", + "indexes-of": "1.0.1", + "uniq": "1.0.1" } } } @@ -13955,7 +13955,7 @@ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } }, "svgo": { @@ -13964,20 +13964,20 @@ "integrity": "sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g==", "dev": true, "requires": { - "coa": "~2.0.1", - "colors": "~1.1.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "~0.1.0", + "coa": "2.0.1", + "colors": "1.1.2", + "css-select": "2.0.2", + "css-select-base-adapter": "0.1.1", "css-tree": "1.0.0-alpha.28", - "css-url-regex": "^1.1.0", - "csso": "^3.5.0", - "js-yaml": "^3.12.0", - "mkdirp": "~0.5.1", - "object.values": "^1.0.4", - "sax": "~1.2.4", - "stable": "~0.1.6", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" + "css-url-regex": "1.1.0", + "csso": "3.5.1", + "js-yaml": "3.12.0", + "mkdirp": "0.5.1", + "object.values": "1.0.4", + "sax": "1.2.4", + "stable": "0.1.8", + "unquote": "1.1.1", + "util.promisify": "1.0.0" } }, "table": { @@ -13986,10 +13986,10 @@ "integrity": "sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw==", "dev": true, "requires": { - "ajv": "^6.6.1", - "lodash": "^4.17.11", + "ajv": "6.6.1", + "lodash": "4.17.11", "slice-ansi": "2.0.0", - "string-width": "^2.1.1" + "string-width": "2.1.1" } }, "tar-stream": { @@ -13998,13 +13998,13 @@ "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", "dev": true, "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" + "bl": "1.2.2", + "buffer-alloc": "1.2.0", + "end-of-stream": "1.4.1", + "fs-constants": "1.0.0", + "readable-stream": "2.3.6", + "to-buffer": "1.1.1", + "xtend": "4.0.1" }, "dependencies": { "end-of-stream": { @@ -14013,7 +14013,7 @@ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { - "once": "^1.4.0" + "once": "1.4.0" } }, "isarray": { @@ -14028,7 +14028,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "readable-stream": { @@ -14037,13 +14037,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -14052,7 +14052,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -14069,8 +14069,8 @@ "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", "dev": true, "requires": { - "temp-dir": "^1.0.0", - "uuid": "^3.0.1" + "temp-dir": "1.0.0", + "uuid": "3.3.2" } }, "text-table": { @@ -14097,8 +14097,8 @@ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "readable-stream": "2.3.6", + "xtend": "4.0.1" }, "dependencies": { "isarray": { @@ -14113,13 +14113,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": 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" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -14128,7 +14128,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -14139,7 +14139,7 @@ "integrity": "sha512-R5/jLkfMvdmDD+seLwN7vB+mhbqzWop5fAjx5IX8/yQq7VhBhzDmhXgaHAOnhnWkCpRMM7gToYHycB0CS/pd+A==", "dev": true, "requires": { - "through2": "^2.0.0" + "through2": "2.0.5" } }, "tildify": { @@ -14148,7 +14148,7 @@ "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", "dev": true, "requires": { - "os-homedir": "^1.0.0" + "os-homedir": "1.0.2" } }, "time-stamp": { @@ -14180,12 +14180,12 @@ "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", "dev": true, "requires": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" + "body": "5.1.0", + "debug": "3.2.6", + "faye-websocket": "0.10.0", + "livereload-js": "2.4.0", + "object-assign": "4.1.1", + "qs": "6.6.0" }, "dependencies": { "debug": { @@ -14194,7 +14194,7 @@ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "object-assign": { @@ -14216,7 +14216,7 @@ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "os-tmpdir": "~1.0.2" + "os-tmpdir": "1.0.2" } }, "to-array": { @@ -14243,7 +14243,7 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -14252,7 +14252,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -14263,10 +14263,10 @@ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" } }, "to-regex-range": { @@ -14275,8 +14275,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "3.0.0", + "repeat-string": "1.6.1" } }, "tough-cookie": { @@ -14285,8 +14285,8 @@ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "psl": "1.1.29", + "punycode": "1.4.1" }, "dependencies": { "punycode": { @@ -14309,7 +14309,7 @@ "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.2" + "escape-string-regexp": "1.0.5" } }, "trim-right": { @@ -14336,7 +14336,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "tweetnacl": { @@ -14351,7 +14351,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "1.1.2" } }, "type-is": { @@ -14361,7 +14361,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "~2.1.18" + "mime-types": "2.1.21" } }, "typeahead.js": { @@ -14369,7 +14369,7 @@ "resolved": "https://registry.npmjs.org/typeahead.js/-/typeahead.js-0.11.1.tgz", "integrity": "sha1-TmTmcbIjEKhgb0rsgFkkuoSwFbg=", "requires": { - "jquery": ">=1.7" + "jquery": "3.3.1" } }, "typedarray": { @@ -14384,9 +14384,9 @@ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" } }, "uglify-to-browserify": { @@ -14408,8 +14408,8 @@ "integrity": "sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==", "dev": true, "requires": { - "buffer": "^3.0.1", - "through": "^2.3.6" + "buffer": "3.6.0", + "through": "2.3.8" } }, "unc-path-regex": { @@ -14435,8 +14435,8 @@ "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", "dev": true, "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" + "unicode-canonical-property-names-ecmascript": "1.0.4", + "unicode-property-aliases-ecmascript": "1.0.4" } }, "unicode-match-property-value-ecmascript": { @@ -14457,10 +14457,10 @@ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" }, "dependencies": { "extend-shallow": { @@ -14469,7 +14469,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "set-value": { @@ -14478,10 +14478,10 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" } } } @@ -14522,8 +14522,8 @@ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "has-value": "0.3.1", + "isobject": "3.0.1" }, "dependencies": { "has-value": { @@ -14532,9 +14532,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" }, "dependencies": { "isobject": { @@ -14574,7 +14574,7 @@ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "2.1.1" } }, "urix": { @@ -14590,7 +14590,7 @@ "dev": true, "optional": true, "requires": { - "prepend-http": "^1.0.1" + "prepend-http": "1.0.4" } }, "url-to-options": { @@ -14617,8 +14617,8 @@ "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", "dev": true, "requires": { - "lru-cache": "2.2.x", - "tmp": "0.0.x" + "lru-cache": "2.2.4", + "tmp": "0.0.33" }, "dependencies": { "lru-cache": { @@ -14641,8 +14641,8 @@ "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" + "define-properties": "1.1.3", + "object.getownpropertydescriptors": "2.0.3" } }, "utils-merge": { @@ -14663,7 +14663,7 @@ "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, "requires": { - "user-home": "^1.1.1" + "user-home": "1.1.1" } }, "validate-npm-package-license": { @@ -14672,8 +14672,8 @@ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "spdx-correct": "3.0.2", + "spdx-expression-parse": "3.0.0" } }, "vendors": { @@ -14688,9 +14688,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "^1.0.0", + "assert-plus": "1.0.0", "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "extsprintf": "1.3.0" } }, "vinyl": { @@ -14699,8 +14699,8 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } }, @@ -14719,12 +14719,12 @@ "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.3.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^2.0.0", - "vinyl": "^1.1.0" + "graceful-fs": "4.1.15", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0", + "strip-bom-stream": "2.0.0", + "vinyl": "1.2.0" }, "dependencies": { "graceful-fs": { @@ -14745,7 +14745,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } }, "vinyl": { @@ -14754,8 +14754,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } } @@ -14767,14 +14767,14 @@ "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", "dev": true, "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" }, "dependencies": { "clone": { @@ -14789,10 +14789,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "through2": { @@ -14801,8 +14801,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } }, "vinyl": { @@ -14811,8 +14811,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "0.2.0", + "clone-stats": "0.0.1" } } } @@ -14823,7 +14823,7 @@ "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", "dev": true, "requires": { - "source-map": "^0.5.1" + "source-map": "0.5.7" } }, "void-elements": { @@ -14838,8 +14838,8 @@ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", "dev": true, "requires": { - "http-parser-js": ">=0.4.0", - "websocket-extensions": ">=0.1.1" + "http-parser-js": "0.5.0", + "websocket-extensions": "0.1.3" } }, "websocket-extensions": { @@ -14860,7 +14860,7 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } }, "window-size": { @@ -14887,7 +14887,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "^0.5.1" + "mkdirp": "0.5.1" } }, "ws": { @@ -14896,9 +14896,9 @@ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "dev": true, "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" + "async-limiter": "1.0.0", + "safe-buffer": "5.1.2", + "ultron": "1.1.1" } }, "xmlhttprequest-ssl": { @@ -14925,9 +14925,9 @@ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", "window-size": "0.1.0" }, "dependencies": { @@ -14945,8 +14945,8 @@ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "dev": true, "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "buffer-crc32": "0.2.13", + "fd-slicer": "1.1.0" } }, "yeast": { diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 0974432a15..a4ea212ece 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -44,7 +44,7 @@ "autoprefixer": "9.3.1", "gulp-clean-css": "4.0.0", "cssnano": "4.1.7", - "gulp-connect": "5.6.1", + "gulp": "3.9.1", "gulp-babel": "8.0.0", "gulp-concat": "2.6.1", "gulp-connect": "5.6.1", @@ -60,14 +60,13 @@ "gulp-wrap": "0.14.0", "gulp-wrap-js": "0.4.1", "jasmine-core": "3.3.0", - "karma": "^3.1.3", + "karma": "3.1.1", "karma-jasmine": "2.0.1", "karma-phantomjs-launcher": "1.0.4", - "less": "^3.9.0", + "less": "3.9.0", "lodash": "4.17.11", "merge-stream": "1.0.1", - "run-sequence": "^2.2.1", - "marked": "^0.5.2", - "event-stream": "3.3.4" + "run-sequence": "2.2.1", + "marked": "^0.5.2" } } diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/developerdashboardintro.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/developerdashboardintro.html deleted file mode 100644 index 5b4bc988c0..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/developerdashboardintro.html +++ /dev/null @@ -1,14 +0,0 @@ -

Start here

-

This section contains the tools to add advanced features to your Umbraco site

-

From here you can explore and install packages, create macros, add data types, and much more. Start by exploring the below links or videos.

- -

Find out more:

- - diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemanagement.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemanagement.controller.js new file mode 100644 index 0000000000..a5e4125742 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemanagement.controller.js @@ -0,0 +1,187 @@ +function ExamineManagementController($scope, umbRequestHelper, $http, $q, $timeout) { + + var vm = this; + + vm.indexerDetails = []; + vm.searcherDetails = []; + vm.loading = true; + vm.viewState = "list"; + vm.selectedIndex = null; + vm.selectedSearcher = null; + vm.searchResults = null; + + vm.showSearchResultDialog = showSearchResultDialog; + vm.showIndexInfo = showIndexInfo; + vm.showSearcherInfo = showSearcherInfo; + vm.search = search; + vm.toggle = toggle; + vm.rebuildIndex = rebuildIndex; + vm.setViewState = setViewState; + vm.nextSearchResultPage = nextSearchResultPage; + vm.prevSearchResultPage = prevSearchResultPage; + vm.goToPageSearchResultPage = goToPageSearchResultPage; + + vm.infoOverlay = null; + + function showSearchResultDialog(values) { + if (vm.searchResults) { + vm.searchResults.overlay = { + title: "Field values", + searchResultValues: values, + view: "views/dashboard/settings/examinemanagementresults.html", + close: function () { + vm.searchResults.overlay = null; + } + }; + } + } + + function nextSearchResultPage(pageNumber) { + search(vm.selectedIndex ? vm.selectedIndex : vm.selectedSearcher, null, pageNumber); + } + function prevSearchResultPage(pageNumber) { + search(vm.selectedIndex ? vm.selectedIndex : vm.selectedSearcher, null, pageNumber); + } + function goToPageSearchResultPage(pageNumber) { + search(vm.selectedIndex ? vm.selectedIndex : vm.selectedSearcher, null, pageNumber); + } + + function setViewState(state) { + vm.searchResults = null; + vm.viewState = state; + } + + function showIndexInfo(index) { + vm.selectedIndex = index; + setViewState("index-details"); + } + + function showSearcherInfo(searcher) { + vm.selectedSearcher = searcher; + setViewState("searcher-details"); + } + + function checkProcessing(index, checkActionName) { + umbRequestHelper.resourcePromise( + $http.post(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", + checkActionName, + { indexName: index.name })), + 'Failed to check index processing') + .then(function(data) { + + if (data !== null && data !== "null") { + + //copy all resulting properties + for (var k in data) { + index[k] = data[k]; + } + index.isProcessing = false; + } else { + $timeout(() => { + //don't continue if we've tried 100 times + if (index.processingAttempts < 100) { + checkProcessing(index, checkActionName); + //add an attempt + index.processingAttempts++; + } else { + //we've exceeded 100 attempts, stop processing + index.isProcessing = false; + } + }, + 1000); + } + }); + } + + function search(searcher, e, pageNumber) { + + //deal with accepting pressing the enter key + if (e && e.keyCode !== 13) { + return; + } + + if (!searcher) { + throw "searcher parameter is required"; + } + + searcher.isProcessing = true; + + umbRequestHelper.resourcePromise( + $http.get(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", + "GetSearchResults", + { + searcherName: searcher.name, + query: encodeURIComponent(vm.searchText), + pageIndex: pageNumber ? (pageNumber - 1) : 0 + })), + 'Failed to search') + .then(searchResults => { + searcher.isProcessing = false; + vm.searchResults = searchResults + vm.searchResults.pageNumber = pageNumber ? pageNumber : 1; + //20 is page size + vm.searchResults.totalPages = Math.ceil(vm.searchResults.totalRecords / 20); + }); + } + + function toggle(provider, propName) { + if (provider[propName] !== undefined) { + provider[propName] = !provider[propName]; + } else { + provider[propName] = true; + } + } + + function rebuildIndex(index) { + if (confirm("This will cause the index to be rebuilt. " + + "Depending on how much content there is in your site this could take a while. " + + "It is not recommended to rebuild an index during times of high website traffic " + + "or when editors are editing content.")) { + + index.isProcessing = true; + index.processingAttempts = 0; + + umbRequestHelper.resourcePromise( + $http.post(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", + "PostRebuildIndex", + { indexName: index.name })), + 'Failed to rebuild index') + .then(function() { + + //rebuilding has started, nothing is returned accept a 200 status code. + //lets poll to see if it is done. + $timeout(() => { checkProcessing(index, "PostCheckRebuildIndex"), 1000 }); + + }); + } + } + + function init() { + //go get the data + + //combine two promises and execute when they are both done + $q.all([ + + //get the indexer details + umbRequestHelper.resourcePromise( + $http.get(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", "GetIndexerDetails")), + 'Failed to retrieve indexer details') + .then(function (data) { + vm.indexerDetails = data; + }), + + //get the searcher details + umbRequestHelper.resourcePromise( + $http.get(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", "GetSearcherDetails")), + 'Failed to retrieve searcher details') + .then(data => { + vm.searcherDetails = data; + }) + ]) + .then(() => { vm.loading = false }); + } + + init(); +} + +angular.module("umbraco").controller("Umbraco.Dashboard.ExamineManagementController", ExamineManagementController); diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemanagement.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemanagement.html index b5f1fd12ed..5f226771e9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemanagement.html +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemanagement.html @@ -1,286 +1,411 @@ -
+
- - -

Examine Management

-
-
+
+ + +

Examine Management

+
+
+
-
+
-
+
+
-
+
-
-
Indexers
-
+
+
Indexers
+
-
-
-
-
Manage Examine's indexes
-
Allows you to view the details of each index and provides some tools for managing the indexes
-
- -
- -
- +
+
+
+
Manage Examine's indexes
+
Allows you to view the details of each index and provides some tools for managing the indexes
-
-
-
- {{indexer.name}} -
- - {{indexer.name}} - -
- The index cannot be read and will need to be rebuilt +
+ +
+ +
+ + -
-
- - -
-
- -
-
    -
  • - Index info & tools - -
    -
    -
    - -
    - -
    - -
    - The process is taking longer than expected, check the umbraco log to see if there have been any errors during this operation -
    -
    - - - - - - - - - - -
     
    Documents in index{{indexer.documentCount}}
    Fields in index{{indexer.fieldCount}}
    -
    -
  • -
  • - Node types - - - - - - - - - - - - - -
    Include node types{{indexer.indexCriteria.IncludeNodeTypes | json}}
    Exclude node types{{indexer.indexCriteria.ExcludeNodeTypes | json}}
    Parent node id{{indexer.indexCriteria.ParentNodeId}}
    -
  • -
  • - System fields - - - - - - - - - - - - - - - - -
     
    NameEnable sortingType
    {{field.Name}}{{field.EnableSorting}}{{field.Type}}
    -
  • -
  • - User fields - - - - - - - - - - - - - - - - -
     
    NameEnable sortingType
    {{field.Name}}{{field.EnableSorting}}{{field.Type}}
    -
  • -
  • - Provider properties - - - - - - -
     
    {{key}}{{val}}
    -
  • -
-
-
- -
-
-
+ +
+ +
+ +
+ +
+
Searchers
+
+ +
+
+
+
Configured Searchers
+
Shows properties and tools for any configured Searcher (i.e. such as a multi-index searcher)
+
+ +
+ +
+ +
+ + +
+
+
+
-
+
-
+ + + ← Back to overview + + -
-
Searchers
-
+
-
-
-
-
Search indexes
-
Allows you to search the indexes and view the searcher properties
+
+ +
+
{{ vm.selectedSearcher.name }}
-
+
-
- -
- -
-
- - {{searcher.name}} - + + +
+ +
+
Search
+
Search the index and view the results
- -
-
    -
  • - Search tools +
    -
    - Hide search results +
    -
    - -
    +
    +
    + - +
    -
    +
    -
    -
    +
    + +
    + +
    + +
    +
    + +
    + + + + ← Back to overview + + + + +
    + +
    + +
    +
    {{ vm.selectedIndex.name }}
    +
    + +
    + + + +
    + +
    +
    Health status
    +
    The health status of the index and if it can be read
    +
    + +
    + +
    + +
    + +
    + +
    +
    {{vm.selectedIndex.healthStatus}}
    +
    + The index cannot be read and will need to be rebuilt +
    + +
    +
    + +
    + +
    + + + +
    + +
    +
    Search
    +
    Search the index and view the results
    +
    + +
    + +
    + +
    +
    + + + - - - - - - - - - - - - - - - -
    ScoreIdValues
    {{result.Score}}{{result.Id}} - - {{key}}: - {{val}} - -
    +
    +
    + + + + + + + + + + + + + + + + +
    ScoreIdName
    {{result.score}}{{result.id}} + {{result.values['nodeName']}}  + + ({{result.fieldCount}} fields) + +
    + +
    + + +
    + +
    + +
    +
    +
    + +
    + +
    + +
    + + + +
    + +
    +
    Index info
    +
    Lists the properties of the index
    +
    + +
    + +
    + + + + + + + +
     
    {{key}}{{val}}
    + +
    + +
    + +
    + + + +
    + +
    +
    Tools
    +
    Tools to manage the index
    +
    + +
    + +
    + +
    +
    + + + + + +
    +
    + +
    + +
    + The process is taking longer than expected, check the umbraco log to see if there have been any errors during this operation +
    + +
    + +
    + This index cannot be rebuilt because it has no assigned IIndexPopulator
    -
  • -
  • - Provider properties - - - - - - -
     
    {{key}}{{val}}
    -
  • -
+
+ +
+
+
+
+
+
- -
- + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemanagementresults.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemanagementresults.html new file mode 100644 index 0000000000..1df737816f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemanagementresults.html @@ -0,0 +1,18 @@ +
+ + + + + + + + + + + + + + +
FieldValue
{{key}}{{val}}
+ +
diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemgmt.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemgmt.controller.js deleted file mode 100644 index f4e78a9dc3..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/examinemgmt.controller.js +++ /dev/null @@ -1,128 +0,0 @@ -function ExamineMgmtController($scope, umbRequestHelper, $log, $http, $q, $timeout) { - - $scope.indexerDetails = []; - $scope.searcherDetails = []; - $scope.loading = true; - - function checkProcessing(indexer, checkActionName) { - umbRequestHelper.resourcePromise( - $http.post(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", - checkActionName, - { indexerName: indexer.name })), - 'Failed to check index processing') - .then(function(data) { - - if (data !== null && data !== "null") { - - //copy all resulting properties - for (var k in data) { - indexer[k] = data[k]; - } - indexer.isProcessing = false; - } else { - $timeout(function() { - //don't continue if we've tried 100 times - if (indexer.processingAttempts < 100) { - checkProcessing(indexer, checkActionName); - //add an attempt - indexer.processingAttempts++; - } else { - //we've exceeded 100 attempts, stop processing - indexer.isProcessing = false; - } - }, - 1000); - } - }); - } - - $scope.search = function(searcher, e) { - if (e && e.keyCode !== 13) { - return; - } - - umbRequestHelper.resourcePromise( - $http.get(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", - "GetSearchResults", - { - searcherName: searcher.name, - query: encodeURIComponent(searcher.searchText), - queryType: searcher.searchType - })), - 'Failed to search') - .then(function(searchResults) { - searcher.isSearching = true; - searcher.searchResults = searchResults; - }); - } - - $scope.toggle = function(provider, propName) { - if (provider[propName] !== undefined) { - provider[propName] = !provider[propName]; - } else { - provider[propName] = true; - } - } - - $scope.rebuildIndex = function(indexer) { - if (confirm("This will cause the index to be rebuilt. " + - "Depending on how much content there is in your site this could take a while. " + - "It is not recommended to rebuild an index during times of high website traffic " + - "or when editors are editing content.")) { - - indexer.isProcessing = true; - indexer.processingAttempts = 0; - - umbRequestHelper.resourcePromise( - $http.post(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", - "PostRebuildIndex", - { indexerName: indexer.name })), - 'Failed to rebuild index') - .then(function() { - - //rebuilding has started, nothing is returned accept a 200 status code. - //lets poll to see if it is done. - $timeout(function() { - checkProcessing(indexer, "PostCheckRebuildIndex"); - }, - 1000); - - }); - } - } - - $scope.closeSearch = function(searcher) { - searcher.isSearching = true; - } - - //go get the data - - //combine two promises and execute when they are both done - $q.all([ - - //get the indexer details - umbRequestHelper.resourcePromise( - $http.get(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", "GetIndexerDetails")), - 'Failed to retrieve indexer details') - .then(function(data) { - $scope.indexerDetails = data; - }), - - //get the searcher details - umbRequestHelper.resourcePromise( - $http.get(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", "GetSearcherDetails")), - 'Failed to retrieve searcher details') - .then(function(data) { - $scope.searcherDetails = data; - for (var s in $scope.searcherDetails) { - $scope.searcherDetails[s].searchType = "text"; - } - }) - ]) - .then(function() { - //all init loading is complete - $scope.loading = false; - }); -} - -angular.module("umbraco").controller("Umbraco.Dashboard.ExamineMgmtController", ExamineMgmtController); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/Global.asax b/src/Umbraco.Web.UI/Global.asax index 53d2d54050..08312748b9 100644 --- a/src/Umbraco.Web.UI/Global.asax +++ b/src/Umbraco.Web.UI/Global.asax @@ -1,2 +1 @@ <%@ Application Inherits="Umbraco.Web.UmbracoApplication" Language="C#" %> - \ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 48a8b9208d..2823908a92 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -88,10 +88,9 @@ - + - diff --git a/src/Umbraco.Web.UI/config/ExamineIndex.Release.config b/src/Umbraco.Web.UI/config/ExamineIndex.Release.config index 300f75ba33..ec0d18aa2d 100644 --- a/src/Umbraco.Web.UI/config/ExamineIndex.Release.config +++ b/src/Umbraco.Web.UI/config/ExamineIndex.Release.config @@ -7,22 +7,4 @@ Index/Search providers can be defined in the UmbracoSettings.config More information and documentation can be found on GitHub: https://github.com/Shazwazza/Examine/ --> - - - - - - - - - - - - - - - - - - - \ No newline at end of file + diff --git a/src/Umbraco.Web.UI/config/ExamineIndex.config b/src/Umbraco.Web.UI/config/ExamineIndex.config index 8d8dcaaf6d..833a65c8d1 100644 --- a/src/Umbraco.Web.UI/config/ExamineIndex.config +++ b/src/Umbraco.Web.UI/config/ExamineIndex.config @@ -4,27 +4,11 @@ Umbraco examine is an extensible indexer and search engine. This configuration file can be extended to create your own index sets. Index/Search providers can be defined in the UmbracoSettings.config -More information and documentation can be found on GitHub: https://github.com/Shazwazza/Examine/ +More information and documentation can be found on Our: +https://our.umbraco.com/Documentation/Reference/Searching/Examine/ +https://our.umbraco.com/Documentation/Reference/Config/ExamineIndex/ +https://our.umbraco.com/Documentation/Reference/Config/ExamineSettings/ + --> - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + diff --git a/src/Umbraco.Web.UI/config/ExamineSettings.Release.config b/src/Umbraco.Web.UI/config/ExamineSettings.Release.config index 31e1193ee9..6b3aaa0372 100644 --- a/src/Umbraco.Web.UI/config/ExamineSettings.Release.config +++ b/src/Umbraco.Web.UI/config/ExamineSettings.Release.config @@ -7,34 +7,14 @@ Index sets can be defined in the ExamineIndex.config if you're using the standar More information and documentation can be found on GitHub: https://github.com/Shazwazza/Examine/ --> + - - - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/config/ExamineSettings.config b/src/Umbraco.Web.UI/config/ExamineSettings.config index 18c5658731..f0fd2b69fc 100644 --- a/src/Umbraco.Web.UI/config/ExamineSettings.config +++ b/src/Umbraco.Web.UI/config/ExamineSettings.config @@ -4,38 +4,20 @@ Umbraco examine is an extensible indexer and search engine. This configuration file can be extended to add your own search/index providers. Index sets can be defined in the ExamineIndex.config if you're using the standard provider model. -More information and documentation can be found on GitHub: https://github.com/Shazwazza/Examine/ +More information and documentation can be found on Our: +https://our.umbraco.com/Documentation/Reference/Searching/Examine/ +https://our.umbraco.com/Documentation/Reference/Config/ExamineIndex/ +https://our.umbraco.com/Documentation/Reference/Config/ExamineSettings/ --> - - - - - - - - - - - - - - + diff --git a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs index 02dede1da9..990aa32ddd 100644 --- a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Services.Changes; using Umbraco.Core.Sync; +using Umbraco.Examine; using Umbraco.Web.Cache; using Umbraco.Web.Composing; using Umbraco.Web.Routing; @@ -48,7 +49,7 @@ namespace Umbraco.Web.Components private BackgroundTaskRunner _processTaskRunner; private bool _started; private IBackgroundTask[] _tasks; - private IExamineManager _examineManager; + private IndexRebuilder _indexRebuilder; public override void Compose(Composition composition) { @@ -87,13 +88,13 @@ namespace Umbraco.Web.Components //rebuild indexes if the server is not synced // NOTE: This will rebuild ALL indexes including the members, if developers want to target specific // indexes then they can adjust this logic themselves. - () => ExamineComponent.RebuildIndexes(false, _examineManager, _logger) + () => ExamineComponent.RebuildIndexes(_indexRebuilder, _logger, false, 5000) } }); }); } - public void Initialize(IRuntimeState runtime, IServerRegistrar serverRegistrar, IServerMessenger serverMessenger, IServerRegistrationService registrationService, ILogger logger, IExamineManager examineManager) + public void Initialize(IRuntimeState runtime, IServerRegistrar serverRegistrar, IServerMessenger serverMessenger, IServerRegistrationService registrationService, ILogger logger, IndexRebuilder indexRebuilder) { _registrar = serverRegistrar as DatabaseServerRegistrar; if (_registrar == null) throw new Exception("panic: registar."); @@ -101,12 +102,10 @@ namespace Umbraco.Web.Components _messenger = serverMessenger as BatchedDatabaseServerMessenger; if (_messenger == null) throw new Exception("panic: messenger"); - _messenger.Startup(); - _runtime = runtime; _logger = logger; _registrationService = registrationService; - _examineManager = examineManager; + _indexRebuilder = indexRebuilder; _touchTaskRunner = new BackgroundTaskRunner("ServerRegistration", new BackgroundTaskRunnerOptions { AutoStart = true }, logger); @@ -115,6 +114,9 @@ namespace Umbraco.Web.Components //We will start the whole process when a successful request is made UmbracoModule.RouteAttempt += RegisterBackgroundTasksOnce; + + // must come last, as it references some _variables + _messenger.Startup(); } /// diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 5444aadcec..4d7a21ffef 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -15,6 +15,7 @@ using Umbraco.Core.Models; using Constants = Umbraco.Core.Constants; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using System.Web.Http.Controllers; +using Examine; using Umbraco.Core.Models.Entities; using Umbraco.Core.Xml; using Umbraco.Web.Models.Mapping; @@ -53,12 +54,13 @@ namespace Umbraco.Web.Editors } } - private readonly UmbracoTreeSearcher _treeSearcher = new UmbracoTreeSearcher(); + private readonly UmbracoTreeSearcher _treeSearcher; private readonly SearchableTreeCollection _searchableTreeCollection; - public EntityController(SearchableTreeCollection searchableTreeCollection) + public EntityController(SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher) { _searchableTreeCollection = searchableTreeCollection; + _treeSearcher = treeSearcher; } /// @@ -121,9 +123,8 @@ namespace Umbraco.Web.Editors return result; var allowedSections = Security.CurrentUser.AllowedSections.ToArray(); - var searchableTrees = _searchableTreeCollection.AsReadOnlyDictionary(); - foreach (var searchableTree in searchableTrees) + foreach (var searchableTree in _searchableTreeCollection.SearchableApplicationTrees) { if (allowedSections.Contains(searchableTree.Value.AppAlias)) { @@ -411,22 +412,18 @@ namespace Umbraco.Web.Editors Direction orderDirection = Direction.Ascending, string filter = "") { - int intId; - - if (int.TryParse(id, out intId)) + if (int.TryParse(id, out var intId)) { return GetPagedChildren(intId, type, pageNumber, pageSize, orderBy, orderDirection, filter); } - Guid guidId; - if (Guid.TryParse(id, out guidId)) + if (Guid.TryParse(id, out _)) { //Not supported currently throw new HttpResponseException(HttpStatusCode.NotFound); } - Udi udiId; - if (Udi.TryParse(id, out udiId)) + if (Udi.TryParse(id, out _)) { //Not supported currently throw new HttpResponseException(HttpStatusCode.NotFound); @@ -444,8 +441,7 @@ namespace Umbraco.Web.Editors //the EntityService cannot search members of a certain type, this is currently not supported and would require //quite a bit of plumbing to do in the Services/Repository, we'll revert to a paged search - long total; - var searchResult = _treeSearcher.ExamineSearch(Umbraco, filter ?? "", type, pageSize, pageNumber - 1, out total, id); + var searchResult = _treeSearcher.ExamineSearch(filter ?? "", type, pageSize, pageNumber - 1, out long total, id); return new PagedResult(total, pageNumber, pageSize) { @@ -481,8 +477,7 @@ namespace Umbraco.Web.Editors var objectType = ConvertToObjectType(type); if (objectType.HasValue) { - long totalRecords; - var entities = Services.EntityService.GetPagedChildren(id, objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter); + var entities = Services.EntityService.GetPagedChildren(id, objectType.Value, pageNumber - 1, pageSize, out var totalRecords, orderBy, orderDirection, filter); if (totalRecords == 0) { @@ -595,15 +590,11 @@ namespace Umbraco.Web.Editors /// /// /// - private IEnumerable ExamineSearch(string query, UmbracoEntityTypes entityType, string searchFrom = null) + private IEnumerable ExamineSearch(string query, UmbracoEntityTypes entityType, string searchFrom = null) { - long total; - return _treeSearcher.ExamineSearch(Umbraco, query, entityType, 200, 0, out total, searchFrom); + return _treeSearcher.ExamineSearch(query, entityType, 200, 0, out _, searchFrom); } - - - private IEnumerable GetResultForChildren(int id, UmbracoEntityTypes entityType) { var objectType = ConvertToObjectType(entityType); diff --git a/src/Umbraco.Web/Editors/ExamineManagementController.cs b/src/Umbraco.Web/Editors/ExamineManagementController.cs index 829c4ccf74..67209c91bd 100644 --- a/src/Umbraco.Web/Editors/ExamineManagementController.cs +++ b/src/Umbraco.Web/Editors/ExamineManagementController.cs @@ -9,12 +9,18 @@ using System.Web.Http; using Examine; using Examine.LuceneEngine; using Examine.LuceneEngine.Providers; +using Lucene.Net.Analysis; +using Lucene.Net.QueryParsers; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Logging; +using Umbraco.Examine; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.Search; +using SearchResult = Umbraco.Web.Models.ContentEditing.SearchResult; +using Version = Lucene.Net.Util.Version; namespace Umbraco.Web.Editors { @@ -24,26 +30,26 @@ namespace Umbraco.Web.Editors private readonly IExamineManager _examineManager; private readonly ILogger _logger; private readonly IRuntimeCacheProvider _runtimeCacheProvider; + private readonly IndexRebuilder _indexRebuilder; + public ExamineManagementController(IExamineManager examineManager, ILogger logger, - IRuntimeCacheProvider runtimeCacheProvider) + IRuntimeCacheProvider runtimeCacheProvider, + IndexRebuilder indexRebuilder) { _examineManager = examineManager; _logger = logger; _runtimeCacheProvider = runtimeCacheProvider; + _indexRebuilder = indexRebuilder; } /// /// Get the details for indexers /// /// - public IEnumerable GetIndexerDetails() + public IEnumerable GetIndexerDetails() { - return _examineManager.IndexProviders.Select(CreateModel).OrderBy(x => - { - //order by name , but strip the "Indexer" from the end if it exists - return x.Name.TrimEnd("Indexer"); - }); + return _examineManager.Indexes.Select(CreateModel).OrderBy(x => x.Name.TrimEnd("Indexer")); } /// @@ -53,229 +59,189 @@ namespace Umbraco.Web.Editors public IEnumerable GetSearcherDetails() { var model = new List( - _examineManager.IndexProviders.Select(indexer => - { - var searcher = indexer.Value.GetSearcher(); - var searcherName = (searcher as BaseLuceneSearcher)?.Name ?? string.Concat(indexer.Key, "Searcher"); - - var indexerModel = new ExamineSearcherModel - { - Name = searcherName - }; - var props = TypeHelper.CachedDiscoverableProperties(searcher.GetType(), mustWrite: false) - //ignore these properties - .Where(x => new[] { "Description" }.InvariantContains(x.Name) == false) - .Where(x => x.GetCustomAttribute() - ?.State != EditorBrowsableState.Never) - .OrderBy(x => x.Name); - foreach (var p in props) - { - indexerModel.ProviderProperties.Add(p.Name, p.GetValue(searcher, null)?.ToString()); - } - - return indexerModel; - }).OrderBy(x => - { - //order by name , but strip the "Searcher" from the end if it exists - return x.Name.TrimEnd("Searcher"); - })); + _examineManager.RegisteredSearchers.Select(searcher => new ExamineSearcherModel { Name = searcher.Name }) + .OrderBy(x => x.Name.TrimEnd("Searcher"))); //order by name , but strip the "Searcher" from the end if it exists return model; } - public ISearchResults GetSearchResults(string searcherName, string query, string queryType) + public SearchResults GetSearchResults(string searcherName, string query, int pageIndex = 0, int pageSize = 20) { - if (queryType == null) - { - throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); - } - if (query.IsNullOrWhiteSpace()) + return SearchResults.Empty(); + + var msg = ValidateSearcher(searcherName, out var searcher); + if (!msg.IsSuccessStatusCode) + throw new HttpResponseException(msg); + + var results = TryParseLuceneQuery(query) + ? searcher.Search(searcher.CreateCriteria().RawQuery(query), maxResults: pageSize * (pageIndex + 1)) + : searcher.Search(query, true, maxResults: pageSize * (pageIndex + 1)); + + var pagedResults = results.Skip(pageIndex * pageSize); + + return new SearchResults { - return LuceneSearchResults.Empty(); - } + TotalRecords = results.TotalItemCount, + Results = pagedResults.Select(x => new SearchResult + { + Id = x.Id, + Score = x.Score, + //order the values by key + Values = new Dictionary(x.Values.OrderBy(y => y.Key).ToDictionary(y => y.Key, y => y.Value)) + }) + }; + } - var msg = ValidateLuceneSearcher(searcherName, out var searcher); - if (msg.IsSuccessStatusCode) + private bool TryParseLuceneQuery(string query) + { + //TODO: I'd assume there would be a more strict way to parse the query but not that i can find yet, for now we'll + // also do this rudimentary check + if (!query.Contains(":")) + return false; + + try { - if (queryType.InvariantEquals("text")) - { - return searcher.Search(query, false); - } - - if (queryType.InvariantEquals("lucene")) - { - return searcher.Search(searcher.CreateCriteria().RawQuery(query)); - } - - throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); + //This will pass with a plain old string without any fields, need to figure out a way to have it properly parse + var parsed = new QueryParser(Version.LUCENE_30, "nodeName", new KeywordAnalyzer()).Parse(query); + return true; + } + catch (ParseException) + { + return false; + } + catch (Exception) + { + return false; } - - throw new HttpResponseException(msg); } /// /// Check if the index has been rebuilt /// - /// + /// /// /// /// This is kind of rudimentary since there's no way we can know that the index has rebuilt, we /// have a listener for the index op complete so we'll just check if that key is no longer there in the runtime cache /// - public ExamineIndexerModel PostCheckRebuildIndex(string indexerName) + public ExamineIndexModel PostCheckRebuildIndex(string indexName) { - var msg = ValidateLuceneIndexer(indexerName, out LuceneIndexer indexer); - if (msg.IsSuccessStatusCode) - { - var cacheKey = "temp_indexing_op_" + indexerName; - var found = ApplicationCache.RuntimeCache.GetCacheItem(cacheKey); + var validate = ValidateIndex(indexName, out var index); + if (!validate.IsSuccessStatusCode) + throw new HttpResponseException(validate); - //if its still there then it's not done - return found != null - ? null - : CreateModel(new KeyValuePair(indexerName, indexer)); - } + validate = ValidatePopulator(indexName); + if (!validate.IsSuccessStatusCode) + throw new HttpResponseException(validate); + + var cacheKey = "temp_indexing_op_" + indexName; + var found = ApplicationCache.RuntimeCache.GetCacheItem(cacheKey); + + //if its still there then it's not done + return found != null + ? null + : CreateModel(index); - throw new HttpResponseException(msg); } /// - /// Rebuilds the index + /// Rebuilds the index /// - /// + /// /// - public HttpResponseMessage PostRebuildIndex(string indexerName) + public HttpResponseMessage PostRebuildIndex(string indexName) { - var msg = ValidateLuceneIndexer(indexerName, out LuceneIndexer indexer); - if (msg.IsSuccessStatusCode) + var validate = ValidateIndex(indexName, out var index); + if (!validate.IsSuccessStatusCode) + return validate; + + validate = ValidatePopulator(indexName); + if (!validate.IsSuccessStatusCode) + return validate; + + _logger.Info("Rebuilding index '{IndexName}'", indexName); + + //remove it in case there's a handler there alraedy + index.IndexOperationComplete -= Indexer_IndexOperationComplete; + + //now add a single handler + index.IndexOperationComplete += Indexer_IndexOperationComplete; + + try { - _logger.Info("Rebuilding index '{IndexerName}'", indexerName); - - //remove it in case there's a handler there alraedy - indexer.IndexOperationComplete -= Indexer_IndexOperationComplete; - - //now add a single handler - indexer.IndexOperationComplete += Indexer_IndexOperationComplete; - - var cacheKey = "temp_indexing_op_" + indexer.Name; + //clear and replace + index.CreateIndex(); + var cacheKey = "temp_indexing_op_" + index.Name; //put temp val in cache which is used as a rudimentary way to know when the indexing is done - ApplicationCache.RuntimeCache.InsertCacheItem(cacheKey, () => "tempValue", TimeSpan.FromMinutes(5), - false); + ApplicationCache.RuntimeCache.InsertCacheItem(cacheKey, () => "tempValue", TimeSpan.FromMinutes(5)); - try - { - indexer.RebuildIndex(); - } - catch (Exception ex) - { - //ensure it's not listening - indexer.IndexOperationComplete -= Indexer_IndexOperationComplete; - Logger.Error(ex, "An error occurred rebuilding index"); - var response = Request.CreateResponse(HttpStatusCode.Conflict); - response.Content = - new - StringContent($"The index could not be rebuilt at this time, most likely there is another thread currently writing to the index. Error: {ex}"); - response.ReasonPhrase = "Could Not Rebuild"; - return response; - } + _indexRebuilder.RebuildIndex(indexName); + + ////populate it + //foreach (var populator in _populators.Where(x => x.IsRegistered(indexName))) + // populator.Populate(index); + + return Request.CreateResponse(HttpStatusCode.OK); + } + catch (Exception ex) + { + //ensure it's not listening + index.IndexOperationComplete -= Indexer_IndexOperationComplete; + Logger.Error(ex, "An error occurred rebuilding index"); + var response = Request.CreateResponse(HttpStatusCode.Conflict); + response.Content = + new + StringContent($"The index could not be rebuilt at this time, most likely there is another thread currently writing to the index. Error: {ex}"); + response.ReasonPhrase = "Could Not Rebuild"; + return response; } - - return msg; } - private ExamineIndexerModel CreateModel(KeyValuePair indexerKeyVal) + + + private ExamineIndexModel CreateModel(IIndex index) { - var indexer = indexerKeyVal.Value; - var indexName = indexerKeyVal.Key; - var indexerModel = new ExamineIndexerModel + var indexName = index.Name; + + if (!(index is IIndexDiagnostics indexDiag)) + indexDiag = new GenericIndexDiagnostics(index); + + + var isHealth = indexDiag.IsHealthy(); + var properties = new Dictionary { - FieldDefinitions = indexer.FieldDefinitionCollection, - Name = indexName + [nameof(IIndexDiagnostics.DocumentCount)] = indexDiag.DocumentCount, + [nameof(IIndexDiagnostics.FieldCount)] = indexDiag.FieldCount, + }; + foreach (var p in indexDiag.Metadata) + properties[p.Key] = p.Value; + + var indexerModel = new ExamineIndexModel + { + Name = indexName, + HealthStatus = isHealth.Success ? (isHealth.Result ?? "Healthy") : (isHealth.Result ?? "Unhealthy"), + ProviderProperties = properties, + CanRebuild = _indexRebuilder.CanRebuild(indexName) }; - var props = TypeHelper.CachedDiscoverableProperties(indexer.GetType(), mustWrite: false) - //ignore these properties - .Where(x => new[] { "IndexerData", "Description", "WorkingFolder" } - .InvariantContains(x.Name) == false) - .OrderBy(x => x.Name); - - foreach (var p in props) - { - var val = p.GetValue(indexer, null); - if (val == null) - { - // Do not warn for new new attribute that is optional - if (string.Equals(p.Name, "DirectoryFactory", StringComparison.InvariantCultureIgnoreCase) == false) - { - Logger - .Warn("Property value was null when setting up property on indexer: " + indexName + - " property: " + p.Name); - } - - val = string.Empty; - } - - indexerModel.ProviderProperties.Add(p.Name, val.ToString()); - } - - if (indexer is LuceneIndexer luceneIndexer) - { - indexerModel.IsLuceneIndex = true; - - if (luceneIndexer.IndexExists()) - { - indexerModel.IsHealthy = luceneIndexer.IsHealthy(out var indexError); - - if (indexerModel.IsHealthy == false) - { - //we cannot continue at this point - indexerModel.Error = indexError.ToString(); - return indexerModel; - } - - indexerModel.DocumentCount = luceneIndexer.GetIndexDocumentCount(); - indexerModel.FieldCount = luceneIndexer.GetIndexFieldCount(); - } - else - { - indexerModel.DocumentCount = 0; - indexerModel.FieldCount = 0; - } - } return indexerModel; } - private HttpResponseMessage ValidateLuceneSearcher(string searcherName, out LuceneSearcher searcher) + private HttpResponseMessage ValidateSearcher(string searcherName, out ISearcher searcher) { - foreach (var indexer in _examineManager.IndexProviders) + //try to get the searcher from the indexes + if (_examineManager.TryGetIndex(searcherName, out var index)) { - var s = indexer.Value.GetSearcher(); - var sName = (s as BaseLuceneSearcher)?.Name ?? string.Concat(indexer.Key, "Searcher"); - if (sName != searcherName) - { - continue; - } - - searcher = s as LuceneSearcher; - - //Found it, return OK - if (searcher != null) - { - return Request.CreateResponse(HttpStatusCode.OK); - } - - //Return an error since it's not the right type - var response = Request.CreateResponse(HttpStatusCode.BadRequest); - response.Content = - new StringContent($"The searcher {searcherName} is not of type {typeof(LuceneSearcher)}"); - response.ReasonPhrase = "Wrong Searcher Type"; - return response; + searcher = index.GetSearcher(); + return Request.CreateResponse(HttpStatusCode.OK); } - searcher = null; + + //if we didn't find anything try to find it by an explicitly declared searcher + if (_examineManager.TryGetSearcher(searcherName, out searcher)) + return Request.CreateResponse(HttpStatusCode.OK); var response1 = Request.CreateResponse(HttpStatusCode.BadRequest); response1.Content = new StringContent($"No searcher found with name = {searcherName}"); @@ -283,29 +249,38 @@ namespace Umbraco.Web.Editors return response1; } - private HttpResponseMessage ValidateLuceneIndexer(string indexerName, out T indexer) - where T : class, IIndexer + private HttpResponseMessage ValidatePopulator(string indexName) { - indexer = null; + if (_indexRebuilder.CanRebuild(indexName)) + return Request.CreateResponse(HttpStatusCode.OK); - if (_examineManager.IndexProviders.ContainsKey(indexerName) - && _examineManager.IndexProviders[indexerName] is T casted) + var response = Request.CreateResponse(HttpStatusCode.BadRequest); + response.Content = new StringContent($"The index {indexName} cannot be rebuilt because it does not have an associated {typeof(IIndexPopulator)}"); + response.ReasonPhrase = "Index cannot be rebuilt"; + return response; + } + + private HttpResponseMessage ValidateIndex(string indexName, out IIndex index) + { + index = null; + + if (_examineManager.TryGetIndex(indexName, out index)) { //return Ok! - indexer = casted; return Request.CreateResponse(HttpStatusCode.OK); } var response = Request.CreateResponse(HttpStatusCode.BadRequest); - response.Content = new StringContent($"No indexer found with name = {indexerName} of type {typeof(T)}"); - response.ReasonPhrase = "Indexer Not Found"; + response.Content = new StringContent($"No index found with name = {indexName}"); + response.ReasonPhrase = "Index Not Found"; return response; } - //static listener so it's not GC'd private void Indexer_IndexOperationComplete(object sender, EventArgs e) { - var indexer = (LuceneIndexer) sender; + var indexer = (LuceneIndex)sender; + + _logger.Debug("Logging operation completed for index {IndexName}", indexer.Name); //ensure it's not listening anymore indexer.IndexOperationComplete -= Indexer_IndexOperationComplete; diff --git a/src/Umbraco.Web/Editors/TemplateQueryController.cs b/src/Umbraco.Web/Editors/TemplateQueryController.cs index f614d38ecb..0d0438138a 100644 --- a/src/Umbraco.Web/Editors/TemplateQueryController.cs +++ b/src/Umbraco.Web/Editors/TemplateQueryController.cs @@ -59,8 +59,7 @@ namespace Umbraco.Web.Editors public QueryResultModel PostTemplateQuery(QueryModel model) { - var umbraco = new UmbracoHelper(UmbracoContext, Services, ApplicationCache); - + var queryResult = new QueryResultModel(); var sb = new StringBuilder(); @@ -72,7 +71,7 @@ namespace Umbraco.Web.Editors timer.Start(); - var currentPage = umbraco.ContentAtRoot().FirstOrDefault(); + var currentPage = Umbraco.ContentAtRoot().FirstOrDefault(); timer.Stop(); var pointerNode = currentPage; @@ -80,7 +79,7 @@ namespace Umbraco.Web.Editors // adjust the "FROM" if (model != null && model.Source != null && model.Source.Id > 0) { - var targetNode = umbraco.Content(model.Source.Id); + var targetNode = Umbraco.Content(model.Source.Id); if (targetNode != null) { diff --git a/src/Umbraco.Web/ExamineExtensions.cs b/src/Umbraco.Web/ExamineExtensions.cs index fa5ce64426..f1ed6c0659 100644 --- a/src/Umbraco.Web/ExamineExtensions.cs +++ b/src/Umbraco.Web/ExamineExtensions.cs @@ -12,7 +12,7 @@ namespace Umbraco.Web /// public static class ExamineExtensions { - public static IEnumerable ToPublishedSearchResults(this IEnumerable results, IPublishedCache cache) + public static IEnumerable ToPublishedSearchResults(this IEnumerable results, IPublishedCache cache) { var list = new List(); diff --git a/src/Umbraco.Web/ExamineStartup.cs b/src/Umbraco.Web/ExamineStartup.cs deleted file mode 100644 index f3a8bc3ef5..0000000000 --- a/src/Umbraco.Web/ExamineStartup.cs +++ /dev/null @@ -1,212 +0,0 @@ -// fixme - Examine is borked -// this cannot compile because it seems to require some changes that are not in Examine v2 -// this should *not* exist, see ExamineComponent instead, which handles everything about Examine - -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using Examine; -//using Examine.Config; -//using Examine.LuceneEngine; -//using Examine.LuceneEngine.Providers; -//using Examine.Providers; -//using Lucene.Net.Index; -//using Lucene.Net.Store; -//using Umbraco.Core; -//using Umbraco.Core.Logging; -//using UmbracoExamine; - -//namespace Umbraco.Web -//{ -// /// -// /// Used to configure Examine during startup for the web application -// /// -// internal class ExamineStartup -// { -// private readonly List _indexesToRebuild = new List(); -// private readonly ApplicationContext _appCtx; -// private readonly ProfilingLogger _profilingLogger; -// private static bool _isConfigured = false; - -// //this is used if we are not the MainDom, in which case we need to ensure that if indexes need rebuilding that this -// //doesn't occur since that should only occur when we are MainDom -// private bool _disableExamineIndexing = false; - -// public ExamineStartup(ApplicationContext appCtx) -// { -// _appCtx = appCtx; -// _profilingLogger = appCtx.ProfilingLogger; -// } - -// /// -// /// Called during the initialize operation of the boot manager process -// /// -// public void Initialize() -// { -// //We want to manage Examine's appdomain shutdown sequence ourselves so first we'll disable Examine's default behavior -// //and then we'll use MainDom to control Examine's shutdown -// ExamineManager.DisableDefaultHostingEnvironmentRegistration(); - -// //we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain -// //terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock -// //which simply checks the existence of the lock file -// DirectoryTracker.DefaultLockFactory = d => -// { -// var simpleFsLockFactory = new NoPrefixSimpleFsLockFactory(d); -// return simpleFsLockFactory; -// }; - -// //This is basically a hack for this item: http://issues.umbraco.org/issue/U4-5976 -// // when Examine initializes it will try to rebuild if the indexes are empty, however in many cases not all of Examine's -// // event handlers will be assigned during bootup when the rebuilding starts which is a problem. So with the examine 0.1.58.2941 build -// // it has an event we can subscribe to in order to cancel this rebuilding process, but what we'll do is cancel it and postpone the rebuilding until the -// // boot process has completed. It's a hack but it works. -// ExamineManager.Instance.BuildingEmptyIndexOnStartup += OnInstanceOnBuildingEmptyIndexOnStartup; - -// //let's deal with shutting down Examine with MainDom -// var examineShutdownRegistered = _appCtx.MainDom.Register(() => -// { -// using (_profilingLogger.TraceDuration("Examine shutting down")) -// { -// //Due to the way Examine's own IRegisteredObject works, we'll first run it with immediate=false and then true so that -// //it's correct subroutines are executed (otherwise we'd have to run this logic manually ourselves) -// ExamineManager.Instance.Stop(false); -// ExamineManager.Instance.Stop(true); -// } -// }); -// if (examineShutdownRegistered) -// { -// _profilingLogger.Logger.Debug("Examine shutdown registered with MainDom"); -// } -// else -// { -// _profilingLogger.Logger.Debug("Examine shutdown not registered, this appdomain is not the MainDom"); - -// //if we could not register the shutdown examine ourselves, it means we are not maindom! in this case all of examine should be disabled -// //from indexing anything on startup!! -// _disableExamineIndexing = true; -// Suspendable.ExamineEvents.SuspendIndexers(); -// } -// } - -// /// -// /// Called during the Complete operation of the boot manager process -// /// -// public void Complete() -// { -// EnsureUnlockedAndConfigured(); - -// //Ok, now that everything is complete we'll check if we've stored any references to index that need rebuilding and run them -// // (see the initialize method for notes) - we'll ensure we remove the event handler too in case examine manager doesn't actually -// // initialize during startup, in which case we want it to rebuild the indexes itself. -// ExamineManager.Instance.BuildingEmptyIndexOnStartup -= OnInstanceOnBuildingEmptyIndexOnStartup; - -// //don't do anything if we have disabled this -// if (_disableExamineIndexing == false) -// { -// foreach (var indexer in _indexesToRebuild) -// { -// indexer.RebuildIndex(); -// } -// } -// } - -// /// -// /// Called to perform the rebuilding indexes on startup if the indexes don't exist -// /// -// public void RebuildIndexes() -// { -// //don't do anything if we have disabled this -// if (_disableExamineIndexing) return; - -// EnsureUnlockedAndConfigured(); - -// //If the developer has explicitly opted out of rebuilding indexes on startup then we -// // should adhere to that and not do it, this means that if they are load balancing things will be -// // out of sync if they are auto-scaling but there's not much we can do about that. -// if (ExamineSettings.Instance.RebuildOnAppStart == false) return; - -// foreach (var indexer in GetIndexesForColdBoot()) -// { -// indexer.RebuildIndex(); -// } -// } - -// /// -// /// The method used to create indexes on a cold boot -// /// -// /// -// /// A cold boot is when the server determines it will not (or cannot) process instructions in the cache table and -// /// will rebuild it's own caches itself. -// /// -// public IEnumerable GetIndexesForColdBoot() -// { -// // NOTE: This is IMPORTANT! ... we don't want to rebuild any index that is already flagged to be re-indexed -// // on startup based on our _indexesToRebuild variable and how Examine auto-rebuilds when indexes are empty. -// // This callback is used above for the DatabaseServerMessenger startup options. - -// // all indexes -// IEnumerable indexes = ExamineManager.Instance.IndexProviderCollection; - -// // except those that are already flagged -// // and are processed in Complete() -// if (_indexesToRebuild.Any()) -// indexes = indexes.Except(_indexesToRebuild); - -// // return -// foreach (var index in indexes) -// yield return index; -// } - -// /// -// /// Must be called to configure each index and ensure it's unlocked before any indexing occurs -// /// -// /// -// /// Indexing rebuilding can occur on a normal boot if the indexes are empty or on a cold boot by the database server messenger. Before -// /// either of these happens, we need to configure the indexes. -// /// -// private void EnsureUnlockedAndConfigured() -// { -// if (_isConfigured) return; - -// _isConfigured = true; - -// foreach (var luceneIndexer in ExamineManager.Instance.IndexProviderCollection.OfType()) -// { -// //We now need to disable waiting for indexing for Examine so that the appdomain is shutdown immediately and doesn't wait for pending -// //indexing operations. We used to wait for indexing operations to complete but this can cause more problems than that is worth because -// //that could end up halting shutdown for a very long time causing overlapping appdomains and many other problems. -// luceneIndexer.WaitForIndexQueueOnShutdown = false; - -// //we should check if the index is locked ... it shouldn't be! We are using simple fs lock now and we are also ensuring that -// //the indexes are not operational unless MainDom is true so if _disableExamineIndexing is false then we should be in charge -// if (_disableExamineIndexing == false) -// { -// var dir = luceneIndexer.GetLuceneDirectory(); -// if (IndexWriter.IsLocked(dir)) -// { -// _profilingLogger.Logger.Info("Forcing index " + luceneIndexer.IndexSetName + " to be unlocked since it was left in a locked state"); -// IndexWriter.Unlock(dir); -// } -// } -// } -// } - -// private void OnInstanceOnBuildingEmptyIndexOnStartup(object sender, BuildingEmptyIndexOnStartupEventArgs args) -// { -// //store the indexer that needs rebuilding because it's empty for when the boot process -// // is complete and cancel this current event so the rebuild process doesn't start right now. -// args.Cancel = true; -// _indexesToRebuild.Add((BaseIndexProvider)args.Indexer); - -// //check if the index is rebuilding due to an error and log it -// if (args.IsHealthy == false) -// { -// var baseIndex = args.Indexer as BaseIndexProvider; -// var name = baseIndex != null ? baseIndex.Name : "[UKNOWN]"; - -// _profilingLogger.Logger.Error(string.Format("The index {0} is rebuilding due to being unreadable/corrupt", name), args.UnhealthyException); -// } -// } -// } -//} diff --git a/src/Umbraco.Web/IPublishedContentQuery.cs b/src/Umbraco.Web/IPublishedContentQuery.cs index 055dcbe181..3ab1c5e3ae 100644 --- a/src/Umbraco.Web/IPublishedContentQuery.cs +++ b/src/Umbraco.Web/IPublishedContentQuery.cs @@ -39,7 +39,7 @@ namespace Umbraco.Web /// /// Searches content. /// - IEnumerable Search(int skip, int take, out int totalRecords, string term, bool useWildCards = true, string indexName = null); + IEnumerable Search(int skip, int take, out long totalRecords, string term, bool useWildCards = true, string indexName = null); /// /// Searches content. @@ -49,6 +49,6 @@ namespace Umbraco.Web /// /// Searches content. /// - IEnumerable Search(int skip, int take, out int totalRecords, Examine.SearchCriteria.ISearchCriteria criteria, Examine.ISearcher searchProvider = null); + IEnumerable Search(int skip, int take, out long totalRecords, Examine.SearchCriteria.ISearchCriteria criteria, Examine.ISearcher searcher = null); } } diff --git a/src/Umbraco.Web/Models/ContentEditing/SearchResult.cs b/src/Umbraco.Web/Models/ContentEditing/SearchResult.cs new file mode 100644 index 0000000000..1cdd539165 --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/SearchResult.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing +{ + [DataContract(Name = "result", Namespace = "")] + public class SearchResult + { + [DataMember(Name = "id")] + public string Id { get; set; } + + [DataMember(Name = "score")] + public float Score { get; set; } + + [DataMember(Name = "fieldCount")] + public int FieldCount => Values?.Count ?? 0; + + [DataMember(Name = "values")] + public IReadOnlyDictionary Values { get; set; } + } +} diff --git a/src/Umbraco.Web/Models/ContentEditing/SearchResultItem.cs b/src/Umbraco.Web/Models/ContentEditing/SearchResultEntity.cs similarity index 86% rename from src/Umbraco.Web/Models/ContentEditing/SearchResultItem.cs rename to src/Umbraco.Web/Models/ContentEditing/SearchResultEntity.cs index 5ba89806d0..a1cca9763d 100644 --- a/src/Umbraco.Web/Models/ContentEditing/SearchResultItem.cs +++ b/src/Umbraco.Web/Models/ContentEditing/SearchResultEntity.cs @@ -3,7 +3,7 @@ namespace Umbraco.Web.Models.ContentEditing { [DataContract(Name = "searchResult", Namespace = "")] - public class SearchResultItem : EntityBasic + public class SearchResultEntity : EntityBasic { /// /// The score of the search result diff --git a/src/Umbraco.Web/Models/ContentEditing/SearchResults.cs b/src/Umbraco.Web/Models/ContentEditing/SearchResults.cs new file mode 100644 index 0000000000..f791d55cab --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/SearchResults.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing +{ + [DataContract(Name = "results", Namespace = "")] + public class SearchResults + { + public static SearchResults Empty() => new SearchResults + { + Results = Enumerable.Empty(), + TotalRecords = 0 + }; + + [DataMember(Name = "totalRecords")] + public long TotalRecords { get; set; } + + [DataMember(Name = "results")] + public IEnumerable Results { get; set; } + } +} diff --git a/src/Umbraco.Web/Models/ContentEditing/TreeSearchResult.cs b/src/Umbraco.Web/Models/ContentEditing/TreeSearchResult.cs index 964ed62c88..22c177190d 100644 --- a/src/Umbraco.Web/Models/ContentEditing/TreeSearchResult.cs +++ b/src/Umbraco.Web/Models/ContentEditing/TreeSearchResult.cs @@ -30,6 +30,6 @@ namespace Umbraco.Web.Models.ContentEditing public string JsFormatterMethod { get; set; } [DataMember(Name = "results")] - public IEnumerable Results { get; set; } + public IEnumerable Results { get; set; } } } diff --git a/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs index bfabfd799a..3e42178fbd 100644 --- a/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs @@ -84,7 +84,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.Trashed, opt => opt.Ignore()) .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); - CreateMap() + CreateMap() .ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(ObjectTypes.GetUdiType(src.NodeObjectType), src.Key))) .ForMember(dest => dest.Icon, opt => opt.MapFrom(src=> GetContentTypeIcon(src))) .ForMember(dest => dest.Trashed, opt => opt.Ignore()) @@ -107,7 +107,7 @@ namespace Umbraco.Web.Models.Mapping } }); - CreateMap() + CreateMap() //default to document icon .ForMember(dest => dest.Score, opt => opt.MapFrom(result => result.Score)) .ForMember(dest => dest.Udi, opt => opt.Ignore()) @@ -123,22 +123,22 @@ namespace Umbraco.Web.Models.Mapping .AfterMap((src, dest) => { //get the icon if there is one - dest.Icon = src.Fields.ContainsKey(UmbracoExamineIndexer.IconFieldName) - ? src.Fields[UmbracoExamineIndexer.IconFieldName] + dest.Icon = src.Values.ContainsKey(UmbracoExamineIndexer.IconFieldName) + ? src.Values[UmbracoExamineIndexer.IconFieldName] : "icon-document"; - dest.Name = src.Fields.ContainsKey("nodeName") ? src.Fields["nodeName"] : "[no name]"; - if (src.Fields.ContainsKey(UmbracoExamineIndexer.NodeKeyFieldName)) + dest.Name = src.Values.ContainsKey("nodeName") ? src.Values["nodeName"] : "[no name]"; + if (src.Values.ContainsKey(UmbracoExamineIndexer.NodeKeyFieldName)) { Guid key; - if (Guid.TryParse(src.Fields[UmbracoExamineIndexer.NodeKeyFieldName], out key)) + if (Guid.TryParse(src.Values[UmbracoExamineIndexer.NodeKeyFieldName], out key)) { dest.Key = key; //need to set the UDI - if (src.Fields.ContainsKey(LuceneIndexer.CategoryFieldName)) + if (src.Values.ContainsKey(LuceneIndex.CategoryFieldName)) { - switch (src.Fields[LuceneIndexer.CategoryFieldName]) + switch (src.Values[LuceneIndex.CategoryFieldName]) { case IndexTypes.Member: dest.Udi = new GuidUdi(Constants.UdiEntityType.Member, dest.Key); @@ -154,10 +154,10 @@ namespace Umbraco.Web.Models.Mapping } } - if (src.Fields.ContainsKey("parentID")) + if (src.Values.ContainsKey("parentID")) { int parentId; - if (int.TryParse(src.Fields["parentID"], out parentId)) + if (int.TryParse(src.Values["parentID"], out parentId)) { dest.ParentId = parentId; } @@ -166,19 +166,19 @@ namespace Umbraco.Web.Models.Mapping dest.ParentId = -1; } } - dest.Path = src.Fields.ContainsKey(UmbracoExamineIndexer.IndexPathFieldName) ? src.Fields[UmbracoExamineIndexer.IndexPathFieldName] : ""; + dest.Path = src.Values.ContainsKey(UmbracoExamineIndexer.IndexPathFieldName) ? src.Values[UmbracoExamineIndexer.IndexPathFieldName] : ""; - if (src.Fields.ContainsKey(LuceneIndexer.ItemTypeFieldName)) + if (src.Values.ContainsKey(LuceneIndex.ItemTypeFieldName)) { - dest.AdditionalData.Add("contentType", src.Fields[LuceneIndexer.ItemTypeFieldName]); + dest.AdditionalData.Add("contentType", src.Values[LuceneIndex.ItemTypeFieldName]); } }); - CreateMap>() - .ConvertUsing(results => results.Select(Mapper.Map).ToList()); + CreateMap>() + .ConvertUsing(results => results.Select(Mapper.Map).ToList()); - CreateMap, IEnumerable>() - .ConvertUsing(results => results.Select(Mapper.Map).ToList()); + CreateMap, IEnumerable>() + .ConvertUsing(results => results.Select(Mapper.Map).ToList()); } /// diff --git a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs index 163284cf86..56d00e8ec9 100644 --- a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs +++ b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs @@ -80,7 +80,7 @@ namespace Umbraco.Web.Mvc /// Exposes an UmbracoHelper /// protected UmbracoHelper Umbraco => _helper - ?? (_helper = new UmbracoHelper(Current.UmbracoContext, Current.Services, Current.ApplicationCache)); + ?? (_helper = new UmbracoHelper(Current.UmbracoContext, Current.Services)); public override void OnActionExecuted(ActionExecutedContext filterContext) { diff --git a/src/Umbraco.Web/Mvc/PluginController.cs b/src/Umbraco.Web/Mvc/PluginController.cs index f2742ce9f0..2b4ebc3f71 100644 --- a/src/Umbraco.Web/Mvc/PluginController.cs +++ b/src/Umbraco.Web/Mvc/PluginController.cs @@ -82,7 +82,7 @@ namespace Umbraco.Web.Mvc get { return _umbracoHelper - ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services, ApplicationCache)); + ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services)); } internal set // tests { diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index 563b315de5..b8b55ae35d 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -83,7 +83,7 @@ namespace Umbraco.Web.Mvc /// Gets the Umbraco helper. /// public UmbracoHelper Umbraco => _umbracoHelper - ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services, ApplicationCache)); + ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services)); /// /// Gets the web security helper. diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index 6fa6750031..bd1dd1ed6b 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -98,8 +98,8 @@ namespace Umbraco.Web.Mvc if (content == null && model is IContentModel) content = ((IContentModel) model).Content; _helper = content == null - ? new UmbracoHelper(UmbracoContext, Services, ApplicationCache) - : new UmbracoHelper(UmbracoContext, Services, ApplicationCache, content); + ? new UmbracoHelper(UmbracoContext, Services) + : new UmbracoHelper(UmbracoContext, Services, content); return _helper; } } diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs index 0f3211b743..99972a27cf 100644 --- a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs @@ -1,15 +1,9 @@ -using System; -using System.Linq; -using System.Text; +using System.Linq; using Umbraco.Core.Logging; using Examine; using Lucene.Net.Documents; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Xml; -using Umbraco.Examine; namespace Umbraco.Web.PropertyEditors { @@ -25,84 +19,7 @@ namespace Umbraco.Web.PropertyEditors : base(logger) { } - internal void DocumentWriting(object sender, Examine.LuceneEngine.DocumentWritingEventArgs e) - { - foreach (var value in e.ValueSet.Values) - { - //if there is a value, it's a string and it's detected as json - if (value.Value.Count > 0 && value.Value[0] != null && (value.Value[0] is string firstVal) && firstVal.DetectIsJson()) - { - try - { - //TODO: We should deserialize this to Umbraco.Core.Models.GridValue instead of doing the below - var json = JsonConvert.DeserializeObject(firstVal); - - //check if this is formatted for grid json - if (json.HasValues && json.TryGetValue("name", out _) && json.TryGetValue("sections", out _)) - { - //get all values and put them into a single field (using JsonPath) - var sb = new StringBuilder(); - foreach (var row in json.SelectTokens("$.sections[*].rows[*]")) - { - var rowName = row["name"].Value(); - var areaVals = row.SelectTokens("$.areas[*].controls[*].value"); - - foreach (var areaVal in areaVals) - { - //TODO: If it's not a string, then it's a json formatted value - - // we cannot really index this in a smart way since it could be 'anything' - if (areaVal.Type == JTokenType.String) - { - var str = areaVal.Value(); - str = XmlHelper.CouldItBeXml(str) ? str.StripHtml() : str; - sb.Append(str); - sb.Append(" "); - - //add the row name as an individual field - e.Document.Add( - new Field( - $"{value.Key}.{rowName}", str, Field.Store.YES, Field.Index.ANALYZED)); - } - - } - } - - if (sb.Length > 0) - { - //First save the raw value to a raw field - e.Document.Add( - new Field( - $"{UmbracoExamineIndexer.RawFieldPrefix}{value.Key}", - firstVal, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); - - //now replace the original value with the combined/cleaned value - e.Document.RemoveField(value.Key); - e.Document.Add( - new Field( - value.Key, - sb.ToString(), Field.Store.YES, Field.Index.ANALYZED)); - } - } - } - catch (InvalidCastException) - { - //swallow...on purpose, there's a chance that this isn't the json format we are looking for - // and we don't want that to affect the website. - } - catch (JsonException) - { - //swallow...on purpose, there's a chance that this isn't json and we don't want that to affect - // the website. - } - catch (ArgumentException) - { - //swallow on purpose to prevent this error: - // Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject. - } - } - - } - } + public override IPropertyIndexValueFactory PropertyIndexValueFactory => new GridPropertyIndexValueFactory(); /// /// Overridden to ensure that the value is validated diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyIndexValueFactory.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyIndexValueFactory.cs new file mode 100644 index 0000000000..c8235d1d11 --- /dev/null +++ b/src/Umbraco.Web/PropertyEditors/GridPropertyIndexValueFactory.cs @@ -0,0 +1,88 @@ +using System; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Umbraco.Core; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Xml; +using Umbraco.Examine; + +namespace Umbraco.Web.PropertyEditors +{ + using System.Collections.Generic; + using System.Linq; + using Umbraco.Core.Models; + + /// + /// Parses the grid value into indexable values + /// + public class GridPropertyIndexValueFactory : IPropertyIndexValueFactory + { + public IEnumerable>> GetIndexValues(Property property, string culture, string segment, bool published) + { + var result = new List>>(); + + var val = property.GetValue(culture, segment, published); + + //if there is a value, it's a string and it's detected as json + if (val is string rawVal && rawVal.DetectIsJson()) + { + try + { + var gridVal = JsonConvert.DeserializeObject(rawVal); + + //get all values and put them into a single field (using JsonPath) + var sb = new StringBuilder(); + foreach (var row in gridVal.Sections.SelectMany(x => x.Rows)) + { + var rowName = row.Name; + + foreach (var control in row.Areas.SelectMany(x => x.Controls)) + { + var controlVal = control.Value; + + //TODO: If it's not a string, then it's a json formatted value - + // we cannot really index this in a smart way since it could be 'anything' + if (controlVal.Type == JTokenType.String) + { + var str = controlVal.Value(); + str = XmlHelper.CouldItBeXml(str) ? str.StripHtml() : str; + sb.Append(str); + sb.Append(" "); + + //add the row name as an individual field + result.Add(new KeyValuePair>($"{property.Alias}.{rowName}", new[] { str })); + } + } + } + + if (sb.Length > 0) + { + //First save the raw value to a raw field + result.Add(new KeyValuePair>($"{UmbracoExamineIndexer.RawFieldPrefix}{property.Alias}", new[] { rawVal })); + + //index the property with the combined/cleaned value + result.Add(new KeyValuePair>(property.Alias, new[] { sb.ToString() })); + } + } + catch (InvalidCastException) + { + //swallow...on purpose, there's a chance that this isn't the json format we are looking for + // and we don't want that to affect the website. + } + catch (JsonException) + { + //swallow...on purpose, there's a chance that this isn't json and we don't want that to affect + // the website. + } + catch (ArgumentException) + { + //swallow on purpose to prevent this error: + // Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject. + } + } + + return result; + } + } +} diff --git a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs index f7d886f637..07c5aac5bb 100644 --- a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs @@ -42,6 +42,8 @@ namespace Umbraco.Web.PropertyEditors : Current.Services.ContentTypeService.Get(contentTypeAlias); } + //fixme: Need to add a custom IPropertyIndexValueFactory for this editor + #region Pre Value Editor protected override IConfigurationEditor CreateConfigurationEditor() => new NestedContentConfigurationEditor(); diff --git a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs index 0b091e0d47..2deb8b8444 100644 --- a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs @@ -6,6 +6,7 @@ using Umbraco.Core.Macros; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; +using Umbraco.Examine; using Umbraco.Web.Macros; namespace Umbraco.Web.PropertyEditors @@ -31,6 +32,7 @@ namespace Umbraco.Web.PropertyEditors protected override IConfigurationEditor CreateConfigurationEditor() => new RichTextConfigurationEditor(); + public override IPropertyIndexValueFactory PropertyIndexValueFactory => new RichTextPropertyIndexValueFactory(); /// /// A custom value editor to ensure that macro syntax is parsed when being persisted and formatted correctly for display in the editor @@ -90,6 +92,21 @@ namespace Umbraco.Web.PropertyEditors return parsed; } } + + internal class RichTextPropertyIndexValueFactory : IPropertyIndexValueFactory + { + public IEnumerable>> GetIndexValues(Property property, string culture, string segment, bool published) + { + var val = property.GetValue(culture, segment, published); + + if (!(val is string strVal)) yield break; + + //index the stripped html values + yield return new KeyValuePair>(property.Alias, new object[] { strVal.StripHtml() }); + //store the raw value + yield return new KeyValuePair>($"{UmbracoExamineIndexer.RawFieldPrefix}{property.Alias}", new object[] { strVal }); + } + } } diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs index cd2f4e5384..5a0fc87cb0 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs @@ -21,13 +21,11 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly ServiceContext _services; - private readonly CacheHelper _appCache; - public MacroContainerValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, CacheHelper appCache) + public MacroContainerValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _services = services ?? throw new ArgumentNullException(nameof(services)); - _appCache = appCache ?? throw new ArgumentNullException(nameof(appCache)); } public override bool IsConverter(PublishedPropertyType propertyType) @@ -50,7 +48,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { var sb = new StringBuilder(); - var umbracoHelper = new UmbracoHelper(umbracoContext, _services, _appCache); + var umbracoHelper = new UmbracoHelper(umbracoContext, _services); MacroTagParser.ParseMacros( source, //callback for when text block is found diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/RelatedLinksLegacyValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/RelatedLinksLegacyValueConverter.cs index 407ea481c4..6c2a4331d0 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/RelatedLinksLegacyValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/RelatedLinksLegacyValueConverter.cs @@ -24,13 +24,11 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly ILogger _logger; private readonly ServiceContext _services; - private readonly CacheHelper _appCache; - public RelatedLinksLegacyValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, CacheHelper appCache, ILogger logger) + public RelatedLinksLegacyValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, ILogger logger) { _umbracoContextAccessor = umbracoContextAccessor; _services = services; - _appCache = appCache; _logger = logger; } @@ -56,7 +54,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters //update the internal links if we have a context if (UmbracoContext.Current != null) { - var helper = new UmbracoHelper(_umbracoContextAccessor.UmbracoContext, _services, _appCache); + var helper = new UmbracoHelper(_umbracoContextAccessor.UmbracoContext, _services); foreach (var a in obj) { var type = a.Value("type"); diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs index 74a5fb313c..7a089b6f9e 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs @@ -22,7 +22,6 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly ServiceContext _services; - private readonly CacheHelper _appCache; public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType) { @@ -31,11 +30,10 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters return PropertyCacheLevel.Snapshot; } - public RteMacroRenderingValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, CacheHelper appCache) + public RteMacroRenderingValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services) { _umbracoContextAccessor = umbracoContextAccessor; _services = services; - _appCache = appCache; } // NOT thread-safe over a request because it modifies the @@ -49,7 +47,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { var sb = new StringBuilder(); - var umbracoHelper = new UmbracoHelper(umbracoContext, _services, _appCache); + var umbracoHelper = new UmbracoHelper(umbracoContext, _services); MacroTagParser.ParseMacros( source, //callback for when text block is found diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs index 49e0d1e9d2..7a8ce65ae3 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs @@ -57,7 +57,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache ValidateAndSetProperty(valueDictionary, val => _sortOrder = Int32.Parse(val), "sortOrder"); ValidateAndSetProperty(valueDictionary, val => _name = val, "nodeName", "__nodeName"); ValidateAndSetProperty(valueDictionary, val => _urlName = val, "urlName"); - ValidateAndSetProperty(valueDictionary, val => _documentTypeAlias = val, "nodeTypeAlias", LuceneIndexer.ItemTypeFieldName); + ValidateAndSetProperty(valueDictionary, val => _documentTypeAlias = val, "nodeTypeAlias", LuceneIndex.ItemTypeFieldName); ValidateAndSetProperty(valueDictionary, val => _documentTypeId = Int32.Parse(val), "nodeType"); //ValidateAndSetProperty(valueDictionary, val => _writerName = val, "writerName"); ValidateAndSetProperty(valueDictionary, val => _creatorName = val, "creatorName", "writerName"); //this is a bit of a hack fix for: U4-1132 diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index 79ff0c33a8..d681d9296e 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -38,7 +38,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // method GetExamineManagerSafe(). // private readonly ISearcher _searchProvider; - private readonly IIndexer _indexProvider; + private readonly IIndex _indexProvider; private readonly XmlStore _xmlStore; private readonly PublishedContentTypeCache _contentTypeCache; @@ -240,8 +240,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache try { - //by default use the internal index - return eMgr.GetSearcher(Constants.Examine.InternalIndexer); + if (eMgr.TryGetIndex(Constants.Examine.InternalIndexer, out var index)) + return index.GetSearcher(); + throw new InvalidOperationException($"No index found by name {Constants.Examine.InternalIndexer}"); } catch (FileNotFoundException) { @@ -353,13 +354,13 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache return null; } - internal CacheValues ConvertFromSearchResult(SearchResult searchResult) + internal CacheValues ConvertFromSearchResult(ISearchResult searchResult) { // note: fixing fields in 7.x, removed by Shan for 8.0 return new CacheValues { - Values = searchResult.Fields, + Values = searchResult.Values, FromExamine = true }; } diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index f0ddf62074..2bc0d7be3f 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -282,16 +282,15 @@ namespace Umbraco.Web #region Search - public static IEnumerable Search(this IPublishedContent content, string term, bool useWildCards = true, string indexName = null) + public static IEnumerable SearchDescendants(this IPublishedContent content, string term, bool useWildCards = true, string indexName = null) { - //TODO: we should pass in the IExamineManager? + //fixme: pass in the IExamineManager - var searcher = string.IsNullOrEmpty(indexName) - ? ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer) - : ExamineManager.Instance.GetSearcher(indexName); + indexName = string.IsNullOrEmpty(indexName) ? Constants.Examine.ExternalIndexer : indexName; + if (!ExamineManager.Instance.TryGetIndex(indexName, out var index)) + throw new InvalidOperationException("No index found with name " + indexName); - if (searcher == null) - throw new InvalidOperationException("No searcher found for index " + indexName); + var searcher = index.GetSearcher(); var t = term.Escape().Value; if (useWildCards) @@ -303,21 +302,15 @@ namespace Umbraco.Web return content.Search(crit, searcher); } - public static IEnumerable SearchDescendants(this IPublishedContent content, string term, bool useWildCards = true, string indexName = null) - { - return content.Search(term, useWildCards, indexName); - } - public static IEnumerable SearchChildren(this IPublishedContent content, string term, bool useWildCards = true, string indexName = null) { - //TODO: we should pass in the IExamineManager? + //fixme: pass in the IExamineManager - var searcher = string.IsNullOrEmpty(indexName) - ? ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer) - : ExamineManager.Instance.GetSearcher(indexName); + indexName = string.IsNullOrEmpty(indexName) ? Constants.Examine.ExternalIndexer : indexName; + if (!ExamineManager.Instance.TryGetIndex(indexName, out var index)) + throw new InvalidOperationException("No index found with name " + indexName); - if (searcher == null) - throw new InvalidOperationException("No searcher found for index " + indexName); + var searcher = index.GetSearcher(); var t = term.Escape().Value; if (useWildCards) @@ -329,13 +322,17 @@ namespace Umbraco.Web return content.Search(crit, searcher); } - public static IEnumerable Search(this IPublishedContent content, Examine.SearchCriteria.ISearchCriteria criteria, Examine.ISearcher searchProvider = null) + public static IEnumerable Search(this IPublishedContent content, Examine.SearchCriteria.ISearchCriteria criteria, ISearcher searchProvider = null) { - //TODO: we should pass in the IExamineManager? + //fixme: pass in the IExamineManager - var s = searchProvider ?? ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer); - - var results = s.Search(criteria); + if (searchProvider == null) + { + if (!ExamineManager.Instance.TryGetIndex(Constants.Examine.ExternalIndexer, out var index)) + throw new InvalidOperationException("No index found with name " + Constants.Examine.ExternalIndexer); + searchProvider = index.GetSearcher(); + } + var results = searchProvider.Search(criteria); return results.ToPublishedSearchResults(UmbracoContext.Current.ContentCache); } diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs index e0fac5773f..04611000b9 100644 --- a/src/Umbraco.Web/PublishedContentQuery.cs +++ b/src/Umbraco.Web/PublishedContentQuery.cs @@ -187,42 +187,43 @@ namespace Umbraco.Web } /// - public IEnumerable Search(int skip, int take, out int totalRecords, string term, bool useWildCards = true, string indexName = null) + public IEnumerable Search(int skip, int take, out long totalRecords, string term, bool useWildCards = true, string indexName = null) { - //TODO: Can we inject IExamineManager? + //fixme: inject IExamineManager - var indexer = string.IsNullOrEmpty(indexName) - ? Examine.ExamineManager.Instance.GetIndexer(Constants.Examine.ExternalIndexer) - : Examine.ExamineManager.Instance.GetIndexer(indexName); + indexName = string.IsNullOrEmpty(indexName) + ? Constants.Examine.ExternalIndexer + : indexName; - if (indexer == null) throw new InvalidOperationException("No index found by name " + indexName); + if (!ExamineManager.Instance.TryGetIndex(indexName, out var index)) + throw new InvalidOperationException($"No index found by name {indexName}"); - var searcher = indexer.GetSearcher(); + var searcher = index.GetSearcher(); - if (skip == 0 && take == 0) - { - var results = searcher.Search(term, useWildCards); - totalRecords = results.TotalItemCount; - return results.ToPublishedSearchResults(_contentCache); - } + var results = skip == 0 && take == 0 + ? searcher.Search(term, true) + : searcher.Search(term, true, maxResults: skip + take); - var criteria = SearchAllFields(term, useWildCards, searcher, indexer); - return Search(skip, take, out totalRecords, criteria, searcher); + totalRecords = results.TotalItemCount; + return results.ToPublishedSearchResults(_contentCache); } /// - public IEnumerable Search(ISearchCriteria criteria, Examine.ISearcher searchProvider = null) + public IEnumerable Search(ISearchCriteria criteria, ISearcher searchProvider = null) { return Search(0, 0, out _, criteria, searchProvider); } /// - public IEnumerable Search(int skip, int take, out int totalRecords, ISearchCriteria criteria, Examine.ISearcher searchProvider = null) + public IEnumerable Search(int skip, int take, out long totalRecords, ISearchCriteria criteria, ISearcher searcher = null) { - - //TODO: Can we inject IExamineManager? - - var searcher = searchProvider ?? Examine.ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer); + //fixme: inject IExamineManager + if (searcher == null) + { + if (!ExamineManager.Instance.TryGetIndex(Constants.Examine.ExternalIndexer, out var index)) + throw new InvalidOperationException($"No index found by name {Constants.Examine.ExternalIndexer}"); + searcher = index.GetSearcher(); + } var results = skip == 0 && take == 0 ? searcher.Search(criteria) @@ -232,28 +233,6 @@ namespace Umbraco.Web return results.ToPublishedSearchResults(_contentCache); } - /// - /// Creates an ISearchCriteria for searching all fields in a . - /// - private ISearchCriteria SearchAllFields(string searchText, bool useWildcards, Examine.ISearcher searcher, Examine.IIndexer indexer) - { - var sc = searcher.CreateCriteria(); - - //if we're dealing with a lucene searcher, we can get all of it's indexed fields, - //else we can get the defined fields for the index. - var searchFields = (searcher is BaseLuceneSearcher luceneSearcher) - ? luceneSearcher.GetAllIndexedFields() - : indexer.FieldDefinitionCollection.Keys; - - //this is what Examine does internally to create ISearchCriteria for searching all fields - var strArray = searchText.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - - sc = useWildcards == false - ? sc.GroupedOr(searchFields, strArray).Compile() - : sc.GroupedOr(searchFields, strArray.Select(x => (IExamineValue)new ExamineValue(Examineness.ComplexWildcard, x.MultipleCharacterWildcard().Value)).ToArray()).Compile(); - return sc; - } - #endregion } diff --git a/src/Umbraco.Web/RelatedLinksTypeConverter.cs b/src/Umbraco.Web/RelatedLinksTypeConverter.cs index 9ed9398d2e..647959b920 100644 --- a/src/Umbraco.Web/RelatedLinksTypeConverter.cs +++ b/src/Umbraco.Web/RelatedLinksTypeConverter.cs @@ -92,7 +92,7 @@ namespace Umbraco.Web } //DO NOT assign to _umbracoHelper variable, this is a singleton class and we cannot assign this based on an UmbracoHelper which is request based - return new UmbracoHelper(UmbracoContext.Current, Current.Services, Current.ApplicationCache); + return new UmbracoHelper(UmbracoContext.Current, Current.Services); } } } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 97cebdb076..63849034a4 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -130,6 +130,8 @@ namespace Umbraco.Web.Runtime composition.Container.RegisterCollectionBuilder() .Add(() => typeLoader.GetTypes()); // fixme which searchable trees?! + composition.Container.Register(new PerRequestLifeTime()); + composition.Container.RegisterCollectionBuilder() .Add(() => typeLoader.GetTypes()); diff --git a/src/Umbraco.Web/Search/ExamineComponent.cs b/src/Umbraco.Web/Search/ExamineComponent.cs index 7a036ef712..d8c1016c3e 100644 --- a/src/Umbraco.Web/Search/ExamineComponent.cs +++ b/src/Umbraco.Web/Search/ExamineComponent.cs @@ -1,14 +1,11 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading; -using System.Xml.Linq; using Examine; using Examine.LuceneEngine; using Examine.LuceneEngine.Providers; -using Lucene.Net.Documents; using Lucene.Net.Index; using Umbraco.Core; using Umbraco.Core.Cache; @@ -19,14 +16,16 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Services.Changes; -using Umbraco.Core.Services.Implement; -using Umbraco.Core.Strings; using Umbraco.Core.Sync; using Umbraco.Web.Cache; -using Umbraco.Web.Composing; -using Umbraco.Web.PropertyEditors; using Umbraco.Examine; using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using Umbraco.Web.Scheduling; +using System.Threading.Tasks; +using Examine.LuceneEngine.Directories; +using LightInject; +using Umbraco.Core.Composing; +using Umbraco.Core.Strings; namespace Umbraco.Web.Search { @@ -37,24 +36,77 @@ namespace Umbraco.Web.Search public sealed class ExamineComponent : UmbracoComponentBase, IUmbracoCoreComponent { private IExamineManager _examineManager; + private IContentValueSetBuilder _contentValueSetBuilder; + private IPublishedContentValueSetBuilder _publishedContentValueSetBuilder; + private IValueSetBuilder _mediaValueSetBuilder; + private IValueSetBuilder _memberValueSetBuilder; private static bool _disableExamineIndexing = false; private static volatile bool _isConfigured = false; private static readonly object IsConfiguredLocker = new object(); private IScopeProvider _scopeProvider; - private UrlSegmentProviderCollection _urlSegmentProviders; private ServiceContext _services; + private static BackgroundTaskRunner _rebuildOnStartupRunner; + private static readonly object RebuildLocker = new object(); // the default enlist priority is 100 // enlist with a lower priority to ensure that anything "default" runs after us // but greater that SafeXmlReaderWriter priority which is 60 private const int EnlistPriority = 80; - internal void Initialize(IRuntimeState runtime, MainDom mainDom, PropertyEditorCollection propertyEditors, IExamineManager examineManager, ProfilingLogger profilingLogger, IScopeProvider scopeProvider, UrlSegmentProviderCollection urlSegmentProviderCollection, ServiceContext services) + public override void Compose(Composition composition) + { + base.Compose(composition); + + //fixme: I cannot do this since RegisterSingleton acts like TryRegisterSingleton and only allows one + //composition.Container.RegisterSingleton(); + //composition.Container.RegisterSingleton(); + //composition.Container.RegisterSingleton(); + //composition.Container.RegisterSingleton(); + + // fixme -- CHANGE THIS WHEN THE DI PR IS MERGED + //fixme: Instead i have to do this, but this means that developers adding their own will also need to do this which isn't ideal + composition.Container.RegisterMany(new[] + { + typeof(MemberIndexPopulator), + typeof(ContentIndexPopulator), + typeof(PublishedContentIndexPopulator), + typeof(MediaIndexPopulator), + }); + + composition.Container.RegisterSingleton(); + composition.Container.RegisterSingleton(); + composition.Container.Register(factory => + new ContentValueSetBuilder( + factory.GetInstance(), + factory.GetInstance>(), + factory.GetInstance(), + true)); + composition.Container.Register(factory => + new ContentValueSetBuilder( + factory.GetInstance(), + factory.GetInstance>(), + factory.GetInstance(), + false)); + composition.Container.RegisterSingleton, MediaValueSetBuilder>(); + composition.Container.RegisterSingleton, MemberValueSetBuilder>(); + } + + internal void Initialize(IRuntimeState runtime, MainDom mainDom, PropertyEditorCollection propertyEditors, + IExamineManager examineManager, ProfilingLogger profilingLogger, + IScopeProvider scopeProvider, IUmbracoIndexesCreator indexCreator, + IndexRebuilder indexRebuilder, ServiceContext services, + IContentValueSetBuilder contentValueSetBuilder, + IPublishedContentValueSetBuilder publishedContentValueSetBuilder, + IValueSetBuilder mediaValueSetBuilder, + IValueSetBuilder memberValueSetBuilder) { _services = services; - _urlSegmentProviders = urlSegmentProviderCollection; _scopeProvider = scopeProvider; _examineManager = examineManager; + _contentValueSetBuilder = contentValueSetBuilder; + _publishedContentValueSetBuilder = publishedContentValueSetBuilder; + _mediaValueSetBuilder = mediaValueSetBuilder; + _memberValueSetBuilder = memberValueSetBuilder; //We want to manage Examine's appdomain shutdown sequence ourselves so first we'll disable Examine's default behavior //and then we'll use MainDom to control Examine's shutdown @@ -63,18 +115,18 @@ namespace Umbraco.Web.Search //we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain //terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock //which simply checks the existence of the lock file - DirectoryTracker.DefaultLockFactory = d => + DirectoryFactory.DefaultLockFactory = d => { var simpleFsLockFactory = new NoPrefixSimpleFsLockFactory(d); return simpleFsLockFactory; }; - + //let's deal with shutting down Examine with MainDom var examineShutdownRegistered = mainDom.Register(() => { using (profilingLogger.TraceDuration("Examine shutting down")) { - ExamineManager.Instance.Dispose(); + _examineManager.Dispose(); } }); @@ -83,14 +135,18 @@ namespace Umbraco.Web.Search profilingLogger.Logger.Debug("Examine shutdown not registered, this appdomain is not the MainDom, Examine will be disabled"); //if we could not register the shutdown examine ourselves, it means we are not maindom! in this case all of examine should be disabled! - Suspendable.ExamineEvents.SuspendIndexers(); + Suspendable.ExamineEvents.SuspendIndexers(profilingLogger.Logger); _disableExamineIndexing = true; return; //exit, do not continue } + //create the indexes and register them with the manager + foreach(var index in indexCreator.Create()) + _examineManager.AddIndex(index); + profilingLogger.Logger.Debug("Examine shutdown registered with MainDom"); - var registeredIndexers = examineManager.IndexProviders.Values.OfType().Count(x => x.EnableDefaultEventHandler); + var registeredIndexers = examineManager.Indexes.OfType().Count(x => x.EnableDefaultEventHandler); profilingLogger.Logger.Info("Adding examine event handlers for {RegisteredIndexers} index providers.", registeredIndexers); @@ -98,8 +154,6 @@ namespace Umbraco.Web.Search if (registeredIndexers == 0) return; - BindGridToExamine(profilingLogger.Logger, examineManager, propertyEditors); - // bind to distributed cache events - this ensures that this logic occurs on ALL servers // that are taking part in a load balanced environment. ContentCacheRefresher.CacheUpdated += ContentCacheRefresherUpdated; @@ -109,64 +163,44 @@ namespace Umbraco.Web.Search EnsureUnlocked(profilingLogger.Logger, examineManager); - RebuildIndexesOnStartup(profilingLogger.Logger); + RebuildIndexes(indexRebuilder, profilingLogger.Logger, true, 5000); } + /// /// Called to rebuild empty indexes on startup /// + /// /// - private void RebuildIndexesOnStartup(ILogger logger) + /// + /// + public static void RebuildIndexes(IndexRebuilder indexRebuilder, ILogger logger, bool onlyEmptyIndexes, int waitMilliseconds = 0) { //TODO: need a way to disable rebuilding on startup - logger.Info("Starting initialize async background thread."); - - // make it async in order not to slow down the boot - // fixme - should be a proper background task else we cannot stop it! - var bg = new Thread(() => + lock(RebuildLocker) { - try + if (_rebuildOnStartupRunner != null && _rebuildOnStartupRunner.IsRunning) { - // rebuilds any empty indexes - RebuildIndexes(true, _examineManager, logger); + logger.Warn("Call was made to RebuildIndexes but the task runner for rebuilding is already running"); + return; } - catch (Exception ex) - { - logger.Error(ex, "Failed to rebuild empty indexes."); - } - }); - bg.Start(); - } - /// - /// Used to rebuild indexes on startup or cold boot - /// - /// - /// - /// - internal static void RebuildIndexes(bool onlyEmptyIndexes, IExamineManager examineManager, ILogger logger) - { - //do not attempt to do this if this has been disabled since we are not the main dom. - //this can be called during a cold boot - if (_disableExamineIndexing) return; + logger.Info("Starting initialize async background thread."); + //do the rebuild on a managed background thread + var task = new RebuildOnStartupTask(indexRebuilder, logger, onlyEmptyIndexes, waitMilliseconds); - EnsureUnlocked(logger, examineManager); + _rebuildOnStartupRunner = new BackgroundTaskRunner( + "RebuildIndexesOnStartup", + //new BackgroundTaskRunnerOptions{ LongRunning= true }, //fixme, this flag doesn't have any affect anymore + logger); - if (onlyEmptyIndexes) - { - foreach (var indexer in examineManager.IndexProviders.Values.Where(x => x.IsIndexNew())) - { - indexer.RebuildIndex(); - } - } - else - { - //do all of them - ExamineManager.Instance.RebuildIndexes(); + _rebuildOnStartupRunner.TryAdd(task); } } + + /// /// Must be called to each index is unlocked before any indexing occurs /// @@ -186,7 +220,7 @@ namespace Umbraco.Web.Search _isConfigured = true; - foreach (var luceneIndexer in examineManager.IndexProviders.Values.OfType()) + foreach (var luceneIndexer in examineManager.Indexes.OfType()) { //We now need to disable waiting for indexing for Examine so that the appdomain is shutdown immediately and doesn't wait for pending //indexing operations. We used to wait for indexing operations to complete but this can cause more problems than that is worth because @@ -205,21 +239,102 @@ namespace Umbraco.Web.Search } } - private static void BindGridToExamine(ILogger logger, IExamineManager examineManager, IEnumerable propertyEditors) + #region Cache refresher updated event handlers + + /// + /// Updates indexes based on content changes + /// + /// + /// + private void ContentCacheRefresherUpdated(ContentCacheRefresher sender, CacheRefresherEventArgs args) { - //bind the grid property editors - this is a hack until http://issues.umbraco.org/issue/U4-8437 - try + if (Suspendable.ExamineEvents.CanIndex == false) + return; + + if (args.MessageType != MessageType.RefreshByPayload) + throw new NotSupportedException(); + + var contentService = _services.ContentService; + + foreach (var payload in (ContentCacheRefresher.JsonPayload[])args.MessageObject) { - var grid = propertyEditors.OfType().FirstOrDefault(); - if (grid != null) + if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove)) { - foreach (var i in examineManager.IndexProviders.Values.OfType()) - i.DocumentWriting += grid.DocumentWriting; + // delete content entirely (with descendants) + // false: remove entirely from all indexes + DeleteIndexForEntity(payload.Id, false); } - } - catch (Exception ex) - { - logger.Error(ex, "Failed to bind grid property editor."); + else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll)) + { + // ExamineEvents does not support RefreshAll + // just ignore that payload + // so what?! + + //fixme: Rebuild the index at this point? + } + else // RefreshNode or RefreshBranch (maybe trashed) + { + // don't try to be too clever - refresh entirely + // there has to be race conds in there ;-( + + var content = contentService.GetById(payload.Id); + if (content == null) + { + // gone fishing, remove entirely from all indexes (with descendants) + DeleteIndexForEntity(payload.Id, false); + continue; + } + + IContent published = null; + if (content.Published && contentService.IsPathPublished(content)) + published = content; + + if (published == null) + DeleteIndexForEntity(payload.Id, true); + + // just that content + ReIndexForContent(content, published != null); + + // branch + if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch)) + { + var masked = published == null ? null : new List(); + const int pageSize = 500; + var page = 0; + var total = long.MaxValue; + while (page * pageSize < total) + { + var descendants = contentService.GetPagedDescendants(content.Id, page++, pageSize, out total, + //order by shallowest to deepest, this allows us to check it's published state without checking every item + ordering: Ordering.By("Path", Direction.Ascending)); + + foreach (var descendant in descendants) + { + published = null; + if (masked != null) // else everything is masked + { + if (masked.Contains(descendant.ParentId) || !descendant.Published) + masked.Add(descendant.Id); + else + published = descendant; + } + + ReIndexForContent(descendant, published != null); + } + } + } + } + + // NOTE + // + // DeleteIndexForEntity is handled by UmbracoContentIndexer.DeleteFromIndex() which takes + // care of also deleting the descendants + // + // ReIndexForContent is NOT taking care of descendants so we have to reload everything + // again in order to process the branch - we COULD improve that by just reloading the + // XML from database instead of reloading content & re-serializing! + // + // BUT ... pretty sure it is! see test "Index_Delete_Index_Item_Ensure_Heirarchy_Removed" } } @@ -276,7 +391,7 @@ namespace Umbraco.Web.Search var mediaService = _services.MediaService; - foreach (var payload in (MediaCacheRefresher.JsonPayload[]) args.MessageObject) + foreach (var payload in (MediaCacheRefresher.JsonPayload[])args.MessageObject) { if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove)) { @@ -292,15 +407,18 @@ namespace Umbraco.Web.Search else // RefreshNode or RefreshBranch (maybe trashed) { var media = mediaService.GetById(payload.Id); - if (media == null || media.Trashed) + if (media == null) { // gone fishing, remove entirely DeleteIndexForEntity(payload.Id, false); continue; } + if (media.Trashed) + DeleteIndexForEntity(payload.Id, true); + // just that media - ReIndexForMedia(media, media.Trashed == false); + ReIndexForMedia(media, !media.Trashed); // branch if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch)) @@ -313,7 +431,7 @@ namespace Umbraco.Web.Search var descendants = mediaService.GetPagedDescendants(media.Id, page++, pageSize, out total); foreach (var descendant in descendants) { - ReIndexForMedia(descendant, descendant.Trashed == false); + ReIndexForMedia(descendant, !descendant.Trashed); } } } @@ -333,9 +451,9 @@ namespace Umbraco.Web.Search if (args.MessageType != MessageType.RefreshByPayload) throw new NotSupportedException(); - + var changedIds = new Dictionary removedIds, List refreshedIds, List otherIds)>(); - + foreach (var payload in (ContentTypeCacheRefresher.JsonPayload[])args.MessageObject) { if (!changedIds.TryGetValue(payload.ItemType, out var idLists)) @@ -354,11 +472,11 @@ namespace Umbraco.Web.Search const int pageSize = 500; - foreach(var ci in changedIds) + foreach (var ci in changedIds) { if (ci.Value.refreshedIds.Count > 0 || ci.Value.otherIds.Count > 0) { - switch(ci.Key) + switch (ci.Key) { case var itemType when itemType == typeof(IContentType).Name: RefreshContentOfContentTypes(ci.Value.refreshedIds.Concat(ci.Value.otherIds).Distinct().ToArray()); @@ -375,7 +493,7 @@ namespace Umbraco.Web.Search //Delete all content of this content/media/member type that is in any content indexer by looking up matched examine docs foreach (var id in ci.Value.removedIds) { - foreach (var index in _examineManager.IndexProviders.Values.OfType()) + foreach (var index in _examineManager.Indexes.OfType()) { var searcher = index.GetSearcher(); @@ -404,7 +522,7 @@ namespace Umbraco.Web.Search const int pageSize = 500; var memberTypes = _services.MemberTypeService.GetAll(memberTypeIds); - foreach(var memberType in memberTypes) + foreach (var memberType in memberTypes) { var page = 0; var total = long.MaxValue; @@ -461,153 +579,33 @@ namespace Umbraco.Web.Search foreach (var c in contentToRefresh) { - IContent published = null; + var isPublished = false; if (c.Published) { - if (publishChecked.TryGetValue(c.ParentId, out var isPublished)) - { - //if the parent's published path has already been verified then this is published - if (isPublished) - published = c; - } - else + if (!publishChecked.TryGetValue(c.ParentId, out isPublished)) { //nothing by parent id, so query the service and cache the result for the next child to check against isPublished = _services.ContentService.IsPathPublished(c); publishChecked[c.Id] = isPublished; - if (isPublished) - published = c; } } - ReIndexForContent(c, published); + ReIndexForContent(c, isPublished); } } } - /// - /// Updates indexes based on content changes - /// - /// - /// - private void ContentCacheRefresherUpdated(ContentCacheRefresher sender, CacheRefresherEventArgs args) - { - if (Suspendable.ExamineEvents.CanIndex == false) - return; + + #endregion - if (args.MessageType != MessageType.RefreshByPayload) - throw new NotSupportedException(); - - var contentService = _services.ContentService; - - foreach (var payload in (ContentCacheRefresher.JsonPayload[]) args.MessageObject) - { - if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove)) - { - // delete content entirely (with descendants) - // false: remove entirely from all indexes - DeleteIndexForEntity(payload.Id, false); - } - else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll)) - { - // ExamineEvents does not support RefreshAll - // just ignore that payload - // so what?! - - //fixme: Rebuild the index at this point? - } - else // RefreshNode or RefreshBranch (maybe trashed) - { - // don't try to be too clever - refresh entirely - // there has to be race conds in there ;-( - - var content = contentService.GetById(payload.Id); - if (content == null || content.Trashed) - { - // gone fishing, remove entirely from all indexes (with descendants) - DeleteIndexForEntity(payload.Id, false); - continue; - } - - IContent published = null; - if (content.Published && contentService.IsPathPublished(content)) - published = content; - - // just that content - ReIndexForContent(content, published); - - // branch - if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch)) - { - var masked = published == null ? null : new List(); - const int pageSize = 500; - var page = 0; - var total = long.MaxValue; - while(page * pageSize < total) - { - var descendants = contentService.GetPagedDescendants(content.Id, page++, pageSize, out total, - //order by shallowest to deepest, this allows us to check it's published state without checking every item - ordering: Ordering.By("Path", Direction.Ascending)); - - foreach (var descendant in descendants) - { - published = null; - if (masked != null) // else everything is masked - { - if (masked.Contains(descendant.ParentId) || !descendant.Published) - masked.Add(descendant.Id); - else - published = descendant; - } - - ReIndexForContent(descendant, published); - } - } - } - } - - // NOTE - // - // DeleteIndexForEntity is handled by UmbracoContentIndexer.DeleteFromIndex() which takes - // care of also deleting the descendants - // - // ReIndexForContent is NOT taking care of descendants so we have to reload everything - // again in order to process the branch - we COULD improve that by just reloading the - // XML from database instead of reloading content & re-serializing! - // - // BUT ... pretty sure it is! see test "Index_Delete_Index_Item_Ensure_Heirarchy_Removed" - } - } - - private void ReIndexForContent(IContent content, IContent published) - { - if (published != null && content.VersionId == published.VersionId) - { - ReIndexForContent(content); // same = both - } - else - { - if (published == null) - { - // remove 'published' - keep 'draft' - DeleteIndexForEntity(content.Id, true); - } - else - { - // index 'published' - don't overwrite 'draft' - ReIndexForContent(published, false); - } - ReIndexForContent(content, true); // index 'draft' - } - } - - private void ReIndexForContent(IContent sender, bool? supportUnpublished = null) + #region ReIndex/Delete for entity + private void ReIndexForContent(IContent sender, bool isPublished) { var actions = DeferedActions.Get(_scopeProvider); if (actions != null) - actions.Add(new DeferedReIndexForContent(this, sender, supportUnpublished)); + actions.Add(new DeferedReIndexForContent(this, sender, isPublished)); else - DeferedReIndexForContent.Execute(this, sender, supportUnpublished); + DeferedReIndexForContent.Execute(this, sender, isPublished); } private void ReIndexForMember(IMember member) @@ -619,17 +617,17 @@ namespace Umbraco.Web.Search DeferedReIndexForMember.Execute(this, member); } - private void ReIndexForMedia(IMedia sender, bool isMediaPublished) + private void ReIndexForMedia(IMedia sender, bool isPublished) { var actions = DeferedActions.Get(_scopeProvider); if (actions != null) - actions.Add(new DeferedReIndexForMedia(this, sender, isMediaPublished)); + actions.Add(new DeferedReIndexForMedia(this, sender, isPublished)); else - DeferedReIndexForMedia.Execute(this, sender, isMediaPublished); + DeferedReIndexForMedia.Execute(this, sender, isPublished); } /// - /// Remove items from any index that doesn't support unpublished content + /// Remove items from an index /// /// /// @@ -642,9 +640,11 @@ namespace Umbraco.Web.Search if (actions != null) actions.Add(new DeferedDeleteIndex(this, entityId, keepIfUnpublished)); else - DeferedDeleteIndex.Execute(this, entityId, keepIfUnpublished); + DeferedDeleteIndex.Execute(this, entityId, keepIfUnpublished); } + #endregion + #region Defered Actions private class DeferedActions { private readonly List _actions = new List(); @@ -683,30 +683,34 @@ namespace Umbraco.Web.Search { private readonly ExamineComponent _examineComponent; private readonly IContent _content; - private readonly bool? _supportUnpublished; + private readonly bool _isPublished; - public DeferedReIndexForContent(ExamineComponent examineComponent, IContent content, bool? supportUnpublished) - { + public DeferedReIndexForContent(ExamineComponent examineComponent, IContent content, bool isPublished) + { _examineComponent = examineComponent; _content = content; - _supportUnpublished = supportUnpublished; + _isPublished = isPublished; } public override void Execute() { - Execute(_examineComponent, _content, _supportUnpublished); + Execute(_examineComponent, _content, _isPublished); } - public static void Execute(ExamineComponent examineComponent, IContent content, bool? supportUnpublished) + public static void Execute(ExamineComponent examineComponent, IContent content, bool isPublished) { - var valueSet = UmbracoContentIndexer.GetValueSets(examineComponent._urlSegmentProviders, examineComponent._services.UserService, content); + foreach (var index in examineComponent._examineManager.Indexes.OfType() + //filter the indexers + .Where(x => isPublished || !x.PublishedValuesOnly) + .Where(x => x.EnableDefaultEventHandler)) + { + //for content we have a different builder for published vs unpublished + var builder = index.PublishedValuesOnly + ? examineComponent._publishedContentValueSetBuilder + : (IValueSetBuilder)examineComponent._contentValueSetBuilder; - ExamineManager.Instance.IndexItems( - valueSet.ToArray(), - examineComponent._examineManager.IndexProviders.Values.OfType() - // only for the specified indexers - .Where(x => supportUnpublished.HasValue == false || supportUnpublished.Value == x.SupportUnpublishedContent) - .Where(x => x.EnableDefaultEventHandler)); + index.IndexItems(builder.GetValueSets(content)); + } } } @@ -730,15 +734,15 @@ namespace Umbraco.Web.Search public static void Execute(ExamineComponent examineComponent, IMedia media, bool isPublished) { - var valueSet = UmbracoContentIndexer.GetValueSets(examineComponent._urlSegmentProviders, examineComponent._services.UserService, media); + var valueSet = examineComponent._mediaValueSetBuilder.GetValueSets(media).ToList(); - ExamineManager.Instance.IndexItems( - valueSet.ToArray(), - examineComponent._examineManager.IndexProviders.Values.OfType() - // index this item for all indexers if the media is not trashed, otherwise if the item is trashed - // then only index this for indexers supporting unpublished media - .Where(x => isPublished || (x.SupportUnpublishedContent)) - .Where(x => x.EnableDefaultEventHandler)); + foreach (var index in examineComponent._examineManager.Indexes.OfType() + //filter the indexers + .Where(x => isPublished || !x.PublishedValuesOnly) + .Where(x => x.EnableDefaultEventHandler)) + { + index.IndexItems(valueSet); + } } } @@ -760,13 +764,13 @@ namespace Umbraco.Web.Search public static void Execute(ExamineComponent examineComponent, IMember member) { - var valueSet = UmbracoMemberIndexer.GetValueSets(member); - - ExamineManager.Instance.IndexItems( - valueSet.ToArray(), - examineComponent._examineManager.IndexProviders.Values.OfType() - //ensure that only the providers are flagged to listen execute - .Where(x => x.EnableDefaultEventHandler)); + var valueSet = examineComponent._memberValueSetBuilder.GetValueSets(member).ToList(); + foreach (var index in examineComponent._examineManager.Indexes.OfType() + //filter the indexers + .Where(x => x.EnableDefaultEventHandler)) + { + index.IndexItems(valueSet); + } } } @@ -790,15 +794,75 @@ namespace Umbraco.Web.Search public static void Execute(ExamineComponent examineComponent, int id, bool keepIfUnpublished) { - ExamineManager.Instance.DeleteFromIndexes( - id.ToString(CultureInfo.InvariantCulture), - examineComponent._examineManager.IndexProviders.Values.OfType() - // if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content, - // otherwise if keepIfUnpublished == false then remove from all indexes - .Where(x => keepIfUnpublished == false || (x is UmbracoContentIndexer && ((UmbracoContentIndexer)x).SupportUnpublishedContent == false)) - .Where(x => x.EnableDefaultEventHandler)); + var strId = id.ToString(CultureInfo.InvariantCulture); + foreach (var index in examineComponent._examineManager.Indexes.OfType() + + .Where(x => (keepIfUnpublished && !x.PublishedValuesOnly) || !keepIfUnpublished) + .Where(x => x.EnableDefaultEventHandler)) + { + index.DeleteFromIndex(strId); + } } } + #endregion + /// + /// Background task used to rebuild empty indexes on startup + /// + private class RebuildOnStartupTask : IBackgroundTask + { + private readonly IndexRebuilder _indexRebuilder; + private readonly ILogger _logger; + private readonly bool _onlyEmptyIndexes; + private readonly int _waitMilliseconds; + + public RebuildOnStartupTask(IndexRebuilder indexRebuilder, ILogger logger, bool onlyEmptyIndexes, int waitMilliseconds = 0) + { + _indexRebuilder = indexRebuilder ?? throw new ArgumentNullException(nameof(indexRebuilder)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _onlyEmptyIndexes = onlyEmptyIndexes; + _waitMilliseconds = waitMilliseconds; + } + + public bool IsAsync => false; + + public void Dispose() + { + } + + public void Run() + { + try + { + // rebuilds indexes + RebuildIndexes(); + } + catch (Exception ex) + { + _logger.Error(ex, "Failed to rebuild empty indexes."); + } + } + + public Task RunAsync(CancellationToken token) + { + throw new NotImplementedException(); + } + + /// + /// Used to rebuild indexes on startup or cold boot + /// + private void RebuildIndexes() + { + //do not attempt to do this if this has been disabled since we are not the main dom. + //this can be called during a cold boot + if (_disableExamineIndexing) return; + + if (_waitMilliseconds > 0) + Thread.Sleep(_waitMilliseconds); + + EnsureUnlocked(_logger, _indexRebuilder.ExamineManager); + _indexRebuilder.RebuildIndexes(_onlyEmptyIndexes); + } + } } } diff --git a/src/Umbraco.Web/Search/ExamineIndexModel.cs b/src/Umbraco.Web/Search/ExamineIndexModel.cs new file mode 100644 index 0000000000..13cd2cbc12 --- /dev/null +++ b/src/Umbraco.Web/Search/ExamineIndexModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using Examine; + +namespace Umbraco.Web.Search +{ + [DataContract(Name = "indexer", Namespace = "")] + public class ExamineIndexModel + { + [DataMember(Name = "name")] + public string Name { get; set; } + + [DataMember(Name = "healthStatus")] + public string HealthStatus { get; set; } + + [DataMember(Name = "isHealthy")] + public bool IsHealthy => HealthStatus == "Healthy"; + + [DataMember(Name = "providerProperties")] + public IReadOnlyDictionary ProviderProperties { get; set; } + + [DataMember(Name = "canRebuild")] + public bool CanRebuild { get; set; } + + } +} diff --git a/src/Umbraco.Web/Search/ExamineIndexerModel.cs b/src/Umbraco.Web/Search/ExamineIndexerModel.cs deleted file mode 100644 index 3ad4edf7e8..0000000000 --- a/src/Umbraco.Web/Search/ExamineIndexerModel.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using Examine; - -namespace Umbraco.Web.Search -{ - [DataContract(Name = "indexer", Namespace = "")] - public class ExamineIndexerModel : ExamineSearcherModel - { - [DataMember(Name = "fieldDefinitions")] - public IEnumerable FieldDefinitions { get; set; } - - /// - /// The number of docs in the index - /// - [DataMember(Name = "documentCount")] - public int DocumentCount { get; set; } - - /// - /// The number of fields in the index - /// - [DataMember(Name = "fieldCount")] - public int FieldCount { get; set; } - - /// - /// Generally will always be true unless someone has created a new non-lucene index - /// - [DataMember(Name = "isLuceneIndex")] - public bool IsLuceneIndex { get; set; } - } -} diff --git a/src/Umbraco.Web/Search/ExamineSearcherModel.cs b/src/Umbraco.Web/Search/ExamineSearcherModel.cs index 3ad932efa2..8b9badfcfa 100644 --- a/src/Umbraco.Web/Search/ExamineSearcherModel.cs +++ b/src/Umbraco.Web/Search/ExamineSearcherModel.cs @@ -11,26 +11,11 @@ namespace Umbraco.Web.Search { public ExamineSearcherModel() { - ProviderProperties = new Dictionary(); } - /// - /// If the index is not healthy this represents the index error state - /// - [DataMember(Name = "error")] - public string Error { get; set; } - - /// - /// If the index can be open/read - /// - [DataMember(Name = "isHealthy")] - public bool IsHealthy { get; set; } - [DataMember(Name = "name")] public string Name { get; set; } - [DataMember(Name = "providerProperties")] - public IDictionary ProviderProperties { get; private set; } } } diff --git a/src/Umbraco.Web/Search/GenericIndexDiagnostics.cs b/src/Umbraco.Web/Search/GenericIndexDiagnostics.cs new file mode 100644 index 0000000000..32c8d43575 --- /dev/null +++ b/src/Umbraco.Web/Search/GenericIndexDiagnostics.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Examine; +using Umbraco.Core; +using Umbraco.Core.Composing; +using Umbraco.Examine; + +namespace Umbraco.Web.Search +{ + /// + /// Used to return diagnostic data for any index + /// + public class GenericIndexDiagnostics : IIndexDiagnostics + { + private readonly IIndex _index; + private static readonly string[] IgnoreProperties = { "Description" }; + + public GenericIndexDiagnostics(IIndex index) + { + _index = index; + } + + public int DocumentCount => -1; //unknown + + public int FieldCount => -1; //unknown + + public Attempt IsHealthy() + { + if (!_index.IndexExists()) + return Attempt.Fail("Does not exist"); + + try + { + var searcher = _index.GetSearcher(); + var result = searcher.Search("test", false); + return Attempt.Succeed(); //if we can search we'll assume it's healthy + } + catch (Exception e) + { + return Attempt.Fail($"Error: {e.Message}"); + } + } + + public IReadOnlyDictionary Metadata + { + get + { + var result = new Dictionary(); + + var props = TypeHelper.CachedDiscoverableProperties(_index.GetType(), mustWrite: false) + .Where(x => IgnoreProperties.InvariantContains(x.Name) == false) + .OrderBy(x => x.Name); + + foreach (var p in props) + { + var val = p.GetValue(_index, null) ?? string.Empty; + + result.Add(p.Name, val); + } + + return result; + } + } + } +} diff --git a/src/Umbraco.Web/Search/IUmbracoIndexesCreator.cs b/src/Umbraco.Web/Search/IUmbracoIndexesCreator.cs new file mode 100644 index 0000000000..58014597d2 --- /dev/null +++ b/src/Umbraco.Web/Search/IUmbracoIndexesCreator.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using Examine; + +namespace Umbraco.Web.Search +{ + /// + /// Used to create the Umbraco indexes + /// + public interface IUmbracoIndexesCreator + { + IEnumerable Create(); + } +} diff --git a/src/Umbraco.Web/Search/LuceneIndexerExtensions.cs b/src/Umbraco.Web/Search/LuceneIndexerExtensions.cs deleted file mode 100644 index 0b0ca2a768..0000000000 --- a/src/Umbraco.Web/Search/LuceneIndexerExtensions.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System; -using System.Linq; -using Examine; -using Examine.LuceneEngine.Providers; -using Examine.Providers; -using Lucene.Net.Index; -using Lucene.Net.Search; -using Lucene.Net.Store; -using Umbraco.Core.Logging; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.Search -{ - /// - /// Extension methods for the LuceneIndexer - /// - internal static class ExamineExtensions - { - /// - /// Checks if the index can be read/opened - /// - /// - /// The exception returned if there was an error - /// - public static bool IsHealthy(this LuceneIndexer indexer, out Exception ex) - { - try - { - using (indexer.GetIndexWriter().GetReader()) - { - ex = null; - return true; - } - } - catch (Exception e) - { - ex = e; - return false; - } - } - - /// - /// Return the number of indexed documents in Lucene - /// - /// - /// - public static int GetIndexDocumentCount(this LuceneIndexer indexer) - { - try - { - if (!((indexer.GetSearcher() as LuceneSearcher)?.GetLuceneSearcher() is IndexSearcher searcher)) - return 0; - - using (searcher) - using (var reader = searcher.IndexReader) - { - return reader.NumDocs(); - } - } - catch (AlreadyClosedException) - { - Current.Logger.Warn(typeof(ExamineExtensions), "Cannot get GetIndexDocumentCount, the writer is already closed"); - return 0; - } - } - - /// - /// Return the total number of fields in the index - /// - /// - /// - public static int GetIndexFieldCount(this LuceneIndexer indexer) - { - try - { - if (!((indexer.GetSearcher() as LuceneSearcher)?.GetLuceneSearcher() is IndexSearcher searcher)) - return 0; - - using (searcher) - using (var reader = searcher.IndexReader) - { - return reader.GetFieldNames(IndexReader.FieldOption.ALL).Count; - } - } - catch (AlreadyClosedException) - { - Current.Logger.Warn(typeof(ExamineExtensions), "Cannot get GetIndexFieldCount, the writer is already closed"); - return 0; - } - } - - /// - /// Check if the index is locked - /// - /// - /// - /// - /// If the index does not exist we'll consider it locked - /// - public static bool IsIndexLocked(this LuceneIndexer indexer) - { - return indexer.IndexExists() == false - || IndexWriter.IsLocked(indexer.GetLuceneDirectory()); - } - - /// - /// The number of documents deleted in the index - /// - /// - /// - public static int GetDeletedDocumentsCount(this LuceneIndexer indexer) - { - try - { - if (!((indexer.GetSearcher() as LuceneSearcher)?.GetLuceneSearcher() is IndexSearcher searcher)) - return 0; - - using (searcher) - using (var reader = searcher.IndexReader) - { - return reader.NumDeletedDocs; - } - } - catch (AlreadyClosedException) - { - Current.Logger.Warn(typeof(ExamineExtensions), "Cannot get GetDeletedDocumentsCount, the writer is already closed"); - return 0; - } - } - } -} diff --git a/src/Umbraco.Web/Search/SearchableTreeCollection.cs b/src/Umbraco.Web/Search/SearchableTreeCollection.cs index d9368c973e..86f4494353 100644 --- a/src/Umbraco.Web/Search/SearchableTreeCollection.cs +++ b/src/Umbraco.Web/Search/SearchableTreeCollection.cs @@ -33,11 +33,7 @@ namespace Umbraco.Web.Search return dictionary; } - // fixme - oh why?! - public IReadOnlyDictionary AsReadOnlyDictionary() - { - return new ReadOnlyDictionary(_dictionary); - } + public IReadOnlyDictionary SearchableApplicationTrees => _dictionary; public SearchableApplicationTree this[string key] => _dictionary[key]; } diff --git a/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs b/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs new file mode 100644 index 0000000000..623bd5b75f --- /dev/null +++ b/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs @@ -0,0 +1,133 @@ +using System.Collections.Generic; +using Umbraco.Core.Logging; +using Umbraco.Core.Services; +using Umbraco.Core.Strings; +using Umbraco.Examine; +using Umbraco.Core.Persistence; +using Umbraco.Core.IO; +using System.IO; +using Lucene.Net.Store; +using Lucene.Net.Analysis.Standard; +using Lucene.Net.Analysis; +using Examine.LuceneEngine; +using Examine; +using Examine.LuceneEngine.Providers; +using System.Linq; +using Umbraco.Core; +using Umbraco.Core.Models; + +namespace Umbraco.Web.Search +{ + /// + /// Creates the indexes used by Umbraco + /// + public class UmbracoIndexesCreator : IUmbracoIndexesCreator + { + //TODO: we should inject the different IValueSetValidator so devs can just register them instead of overriding this class? + + public UmbracoIndexesCreator(ProfilingLogger profilingLogger, + ILocalizationService languageService, + IPublicAccessService publicAccessService, + IMemberService memberService) + { + ProfilingLogger = profilingLogger ?? throw new System.ArgumentNullException(nameof(profilingLogger)); + LanguageService = languageService ?? throw new System.ArgumentNullException(nameof(languageService)); + PublicAccessService = publicAccessService ?? throw new System.ArgumentNullException(nameof(publicAccessService)); + MemberService = memberService ?? throw new System.ArgumentNullException(nameof(memberService)); + } + + protected ProfilingLogger ProfilingLogger { get; } + protected ILocalizationService LanguageService { get; } + protected IPublicAccessService PublicAccessService { get; } + protected IMemberService MemberService { get; } + + /// + /// Creates the Umbraco indexes + /// + /// + public IEnumerable Create() + { + return new [] + { + CreateInternalIndex(), + CreateExternalIndex(), + CreateMemberIndex() + }; + } + + private IIndex CreateInternalIndex() + { + var index = new UmbracoContentIndexer( + Constants.UmbracoIndexes.InternalIndexName, + //fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes + UmbracoExamineIndexer.UmbracoIndexFieldDefinitions, + GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.InternalIndexPath), + new CultureInvariantWhitespaceAnalyzer(), + ProfilingLogger, + LanguageService, + GetContentValueSetValidator()); + return index; + } + + private IIndex CreateExternalIndex() + { + var index = new UmbracoContentIndexer( + Constants.UmbracoIndexes.ExternalIndexName, + //fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes + UmbracoExamineIndexer.UmbracoIndexFieldDefinitions, + GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.ExternalIndexPath), + new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30), + ProfilingLogger, + LanguageService, + GetPublishedContentValueSetValidator()); + return index; + } + + private IIndex CreateMemberIndex() + { + var index = new UmbracoMemberIndexer( + Constants.UmbracoIndexes.MembersIndexName, + //fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes + UmbracoExamineIndexer.UmbracoIndexFieldDefinitions, + GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.MembersIndexPath), + new CultureInvariantWhitespaceAnalyzer(), + ProfilingLogger, + GetMemberValueSetValidator()); + return index; + } + + public virtual Lucene.Net.Store.Directory GetFileSystemLuceneDirectory(string name) + { + var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Data), "TEMP", "ExamineIndexes", name)); + if (!dirInfo.Exists) + System.IO.Directory.CreateDirectory(dirInfo.FullName); + + var luceneDir = new SimpleFSDirectory(dirInfo); + //we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain + //terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock + //which simply checks the existence of the lock file + luceneDir.SetLockFactory(new NoPrefixSimpleFsLockFactory(dirInfo)); + return luceneDir; + } + + public virtual IContentValueSetValidator GetContentValueSetValidator() + { + return new ContentValueSetValidator(false, true, PublicAccessService); + } + + public virtual IContentValueSetValidator GetPublishedContentValueSetValidator() + { + return new ContentValueSetValidator(true, false, PublicAccessService); + } + + /// + /// Returns the for the member indexer + /// + /// + public virtual IValueSetValidator GetMemberValueSetValidator() + { + return new MemberValueSetValidator(); + } + + } +} diff --git a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs index 262c2c80e3..9aab30edae 100644 --- a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs +++ b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs @@ -11,15 +11,28 @@ using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Trees; +using SearchResult = Examine.SearchResult; namespace Umbraco.Web.Search { - internal class UmbracoTreeSearcher + /// + /// Used for internal Umbraco implementations of + /// + public class UmbracoTreeSearcher { + private readonly IExamineManager _examineManager; + private readonly UmbracoHelper _umbracoHelper; + + public UmbracoTreeSearcher(IExamineManager examineManager, UmbracoHelper umbracoHelper) + { + _examineManager = examineManager ?? throw new ArgumentNullException(nameof(examineManager)); + _umbracoHelper = umbracoHelper ?? throw new ArgumentNullException(nameof(umbracoHelper)); + } + /// /// Searches for results based on the entity type /// - /// /// /// /// @@ -29,8 +42,7 @@ namespace Umbraco.Web.Search /// /// /// - public IEnumerable ExamineSearch( - UmbracoHelper umbracoHelper, + public IEnumerable ExamineSearch( string query, UmbracoEntityTypes entityType, int pageSize, @@ -39,16 +51,16 @@ namespace Umbraco.Web.Search var sb = new StringBuilder(); string type; - var indexer = Constants.Examine.InternalIndexer; + var indexName = Constants.Examine.InternalIndexer; var fields = new[] { "id", "__NodeId" }; - var umbracoContext = umbracoHelper.UmbracoContext; + var umbracoContext = _umbracoHelper.UmbracoContext; //TODO: WE should really just allow passing in a lucene raw query switch (entityType) { case UmbracoEntityTypes.Member: - indexer = Constants.Examine.InternalMemberIndexer; + indexName = Constants.Examine.InternalMemberIndexer; type = "member"; fields = new[] { "id", "__NodeId", "email", "loginName" }; if (searchFrom != null && searchFrom != Constants.Conventions.MemberTypes.AllMembersListId && searchFrom.Trim() != "-1") @@ -72,7 +84,10 @@ namespace Umbraco.Web.Search throw new NotSupportedException("The " + typeof(UmbracoTreeSearcher) + " currently does not support searching against object type " + entityType); } - var internalSearcher = ExamineManager.Instance.GetSearcher(indexer); + if (!_examineManager.TryGetIndex(indexName, out var index)) + throw new InvalidOperationException("No index found by name " + indexName); + + var internalSearcher = index.GetSearcher(); //build a lucene query: // the __nodeName will be boosted 10x without wildcards @@ -95,7 +110,7 @@ namespace Umbraco.Web.Search if (searchFrom.IsNullOrWhiteSpace() && query.IsNullOrWhiteSpace()) { totalFound = 0; - return new List(); + return new List(); } //update the query with the query term @@ -129,7 +144,7 @@ namespace Umbraco.Web.Search if (searchFrom.IsNullOrWhiteSpace() && trimmed.IsNullOrWhiteSpace()) { totalFound = 0; - return new List(); + return new List(); } //update the query with the query term @@ -197,7 +212,7 @@ namespace Umbraco.Web.Search case UmbracoEntityTypes.Media: return MediaFromSearchResults(pagedResult); case UmbracoEntityTypes.Document: - return ContentFromSearchResults(umbracoHelper, pagedResult); + return ContentFromSearchResults(pagedResult); default: throw new NotSupportedException("The " + typeof(UmbracoTreeSearcher) + " currently does not support searching against object type " + entityType); } @@ -205,15 +220,13 @@ namespace Umbraco.Web.Search private void AppendPath(StringBuilder sb, UmbracoObjectTypes objectType, int[] startNodeIds, string searchFrom, IEntityService entityService) { - if (sb == null) throw new ArgumentNullException("sb"); - if (entityService == null) throw new ArgumentNullException("entityService"); + if (sb == null) throw new ArgumentNullException(nameof(sb)); + if (entityService == null) throw new ArgumentNullException(nameof(entityService)); - Udi udi; - Udi.TryParse(searchFrom, true, out udi); + Udi.TryParse(searchFrom, true, out var udi); searchFrom = udi == null ? searchFrom : entityService.GetId(udi).Result.ToString(); - int searchFromId; - var entityPath = int.TryParse(searchFrom, out searchFromId) && searchFromId > 0 + var entityPath = int.TryParse(searchFrom, out var searchFromId) && searchFromId > 0 ? entityService.GetAllPaths(objectType, searchFromId).FirstOrDefault() : null; if (entityPath != null) @@ -265,9 +278,9 @@ namespace Umbraco.Web.Search /// /// /// - private IEnumerable MemberFromSearchResults(SearchResult[] results) + private IEnumerable MemberFromSearchResults(ISearchResult[] results) { - var mapped = Mapper.Map>(results).ToArray(); + var mapped = Mapper.Map>(results).ToArray(); //add additional data foreach (var m in mapped) { @@ -278,14 +291,13 @@ namespace Umbraco.Web.Search } var searchResult = results.First(x => x.Id == m.Id.ToString()); - if (searchResult.Fields.ContainsKey("email") && searchResult.Fields["email"] != null) + if (searchResult.Values.ContainsKey("email") && searchResult.Values["email"] != null) { - m.AdditionalData["Email"] = results.First(x => x.Id == m.Id.ToString()).Fields["email"]; + m.AdditionalData["Email"] = results.First(x => x.Id == m.Id.ToString()).Values["email"]; } - if (searchResult.Fields.ContainsKey("__key") && searchResult.Fields["__key"] != null) + if (searchResult.Values.ContainsKey("__key") && searchResult.Values["__key"] != null) { - Guid key; - if (Guid.TryParse(searchResult.Fields["__key"], out key)) + if (Guid.TryParse(searchResult.Values["__key"], out var key)) { m.Key = key; } @@ -299,9 +311,9 @@ namespace Umbraco.Web.Search /// /// /// - private IEnumerable MediaFromSearchResults(IEnumerable results) + private IEnumerable MediaFromSearchResults(IEnumerable results) { - var mapped = Mapper.Map>(results).ToArray(); + var mapped = Mapper.Map>(results).ToArray(); //add additional data foreach (var m in mapped) { @@ -317,19 +329,18 @@ namespace Umbraco.Web.Search /// /// Returns a collection of entities for content based on search results /// - /// /// /// - private IEnumerable ContentFromSearchResults(UmbracoHelper umbracoHelper, IEnumerable results) + private IEnumerable ContentFromSearchResults(IEnumerable results) { - var mapped = Mapper.Map>(results).ToArray(); + var mapped = Mapper.Map>(results).ToArray(); //add additional data foreach (var m in mapped) { var intId = m.Id.TryConvertTo(); if (intId.Success) { - m.AdditionalData["Url"] = umbracoHelper.Url(intId.Result); + m.AdditionalData["Url"] = _umbracoHelper.Url(intId.Result); } } return mapped; diff --git a/src/Umbraco.Web/Suspendable.cs b/src/Umbraco.Web/Suspendable.cs index beb0029f4f..3317afe7a4 100644 --- a/src/Umbraco.Web/Suspendable.cs +++ b/src/Umbraco.Web/Suspendable.cs @@ -1,6 +1,7 @@ using System; using Examine; using Examine.Providers; +using Umbraco.Core.Logging; using Umbraco.Core.Composing; using Umbraco.Examine; using Umbraco.Web.Cache; @@ -63,25 +64,23 @@ namespace Umbraco.Web } } - public static void SuspendIndexers() + public static void SuspendIndexers(ILogger logger) { - Current.ProfilingLogger.Logger.Info(typeof (ExamineEvents), "Suspend indexers."); + logger.Info(typeof (ExamineEvents), "Suspend indexers."); _suspended = true; } - public static void ResumeIndexers() + public static void ResumeIndexers(IndexRebuilder indexRebuilder, ILogger logger) { _suspended = false; - Current.ProfilingLogger.Logger.Info(typeof (ExamineEvents), "Resume indexers (rebuild:{Tried}).", _tried); + logger.Info(typeof (ExamineEvents), "Resume indexers (rebuild:{Tried}).", _tried); if (_tried == false) return; _tried = false; - // fixme - could we fork this on a background thread? //TODO: when resuming do we always want a full rebuild of all indexes? - // fixme - can we inject IExamineManager somehow? - ExamineComponent.RebuildIndexes(false, ExamineManager.Instance, Current.Logger); + ExamineComponent.RebuildIndexes(indexRebuilder, logger, false); } } diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index c0b2126d5e..d2b94c815b 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -35,7 +35,12 @@ namespace Umbraco.Web.Trees [SearchableTree("searchResultFormatter", "configureContentResult")] public class ContentTreeController : ContentTreeControllerBase, ISearchableTree { - private readonly UmbracoTreeSearcher _treeSearcher = new UmbracoTreeSearcher(); + private readonly UmbracoTreeSearcher _treeSearcher; + + public ContentTreeController(UmbracoTreeSearcher treeSearcher) + { + _treeSearcher = treeSearcher; + } protected override int RecycleBinId => Constants.System.RecycleBinContent; @@ -314,9 +319,9 @@ namespace Umbraco.Web.Trees menuItem.OpensDialog = opensDialog; } - public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) + public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) { - return _treeSearcher.ExamineSearch(Umbraco, query, UmbracoEntityTypes.Document, pageSize, pageIndex, out totalFound, searchFrom); + return _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Document, pageSize, pageIndex, out totalFound, searchFrom); } } } diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs index 43e5b03f2f..0ef3c073eb 100644 --- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs @@ -142,10 +142,10 @@ namespace Umbraco.Web.Trees return menu; } - public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) + public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) { var results = Services.EntityService.GetPagedDescendants(UmbracoObjectTypes.DocumentType, pageIndex, pageSize, out totalFound, filter: query); - return Mapper.Map>(results); + return Mapper.Map>(results); } } } diff --git a/src/Umbraco.Web/Trees/DataTypeTreeController.cs b/src/Umbraco.Web/Trees/DataTypeTreeController.cs index 6c89f4a1dc..0970481357 100644 --- a/src/Umbraco.Web/Trees/DataTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/DataTypeTreeController.cs @@ -142,10 +142,10 @@ namespace Umbraco.Web.Trees return menu; } - public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) + public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) { var results = Services.EntityService.GetPagedDescendants(UmbracoObjectTypes.DataType, pageIndex, pageSize, out totalFound, filter: query); - return Mapper.Map>(results); + return Mapper.Map>(results); } } } diff --git a/src/Umbraco.Web/Trees/ISearchableTree.cs b/src/Umbraco.Web/Trees/ISearchableTree.cs index 6e52b054b4..4146bfaf45 100644 --- a/src/Umbraco.Web/Trees/ISearchableTree.cs +++ b/src/Umbraco.Web/Trees/ISearchableTree.cs @@ -21,6 +21,6 @@ namespace Umbraco.Web.Trees /// A starting point for the search, generally a node id, but for members this is a member type alias /// /// - IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null); + IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null); } } diff --git a/src/Umbraco.Web/Trees/MediaTreeController.cs b/src/Umbraco.Web/Trees/MediaTreeController.cs index 20804d4cf8..8533081dde 100644 --- a/src/Umbraco.Web/Trees/MediaTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTreeController.cs @@ -35,7 +35,12 @@ namespace Umbraco.Web.Trees [SearchableTree("searchResultFormatter", "configureMediaResult")] public class MediaTreeController : ContentTreeControllerBase, ISearchableTree { - private readonly UmbracoTreeSearcher _treeSearcher = new UmbracoTreeSearcher(); + private readonly UmbracoTreeSearcher _treeSearcher; + + public MediaTreeController(UmbracoTreeSearcher treeSearcher) + { + _treeSearcher = treeSearcher; + } protected override int RecycleBinId => Constants.System.RecycleBinMedia; @@ -159,9 +164,9 @@ namespace Umbraco.Web.Trees return HasPathAccess(entity, queryStrings); } - public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) + public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) { - return _treeSearcher.ExamineSearch(Umbraco, query, UmbracoEntityTypes.Media, pageSize, pageIndex, out totalFound, searchFrom); + return _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Media, pageSize, pageIndex, out totalFound, searchFrom); } internal override IEnumerable GetChildrenFromEntityService(int entityId) diff --git a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs index 547199676a..8b3ad5e8cd 100644 --- a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs @@ -133,10 +133,10 @@ namespace Umbraco.Web.Trees return menu; } - public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) + public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) { var results = Services.EntityService.GetPagedDescendants(UmbracoObjectTypes.MediaType, pageIndex, pageSize, out totalFound, filter: query); - return Mapper.Map>(results); + return Mapper.Map>(results); } } } diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web/Trees/MemberTreeController.cs index 68819351c0..ae2ad1824d 100644 --- a/src/Umbraco.Web/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web/Trees/MemberTreeController.cs @@ -33,13 +33,14 @@ namespace Umbraco.Web.Trees [SearchableTree("searchResultFormatter", "configureMemberResult")] public class MemberTreeController : TreeController, ISearchableTree { - public MemberTreeController() + public MemberTreeController(UmbracoTreeSearcher treeSearcher) { + _treeSearcher = treeSearcher; _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); _isUmbracoProvider = _provider.IsUmbracoMembershipProvider(); } - private readonly UmbracoTreeSearcher _treeSearcher = new UmbracoTreeSearcher(); + private readonly UmbracoTreeSearcher _treeSearcher; private readonly MembershipProvider _provider; private readonly bool _isUmbracoProvider; @@ -191,9 +192,9 @@ namespace Umbraco.Web.Trees return menu; } - public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) + public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) { - return _treeSearcher.ExamineSearch(Umbraco, query, UmbracoEntityTypes.Member, pageSize, pageIndex, out totalFound, searchFrom); + return _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Member, pageSize, pageIndex, out totalFound, searchFrom); } } } diff --git a/src/Umbraco.Web/Trees/TemplatesTreeController.cs b/src/Umbraco.Web/Trees/TemplatesTreeController.cs index 3fc005d670..56f47695a0 100644 --- a/src/Umbraco.Web/Trees/TemplatesTreeController.cs +++ b/src/Umbraco.Web/Trees/TemplatesTreeController.cs @@ -133,10 +133,10 @@ namespace Umbraco.Web.Trees : null; } - public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) + public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) { var results = Services.EntityService.GetPagedDescendants(UmbracoObjectTypes.Template, pageIndex, pageSize, out totalFound, filter: query); - return Mapper.Map>(results); + return Mapper.Map>(results); } } } diff --git a/src/Umbraco.Web/UI/Controls/UmbracoControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoControl.cs index 744b77ac50..923ab00c6b 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoControl.cs @@ -16,10 +16,10 @@ namespace Umbraco.Web.UI.Controls { private UrlHelper _url; - protected UmbracoControl(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) + protected UmbracoControl(UmbracoContext umbracoContext, ServiceContext services) { UmbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); - Umbraco = new UmbracoHelper(umbracoContext, services, appCache); + Umbraco = new UmbracoHelper(umbracoContext, services); // fixme inject somehow Logger = Current.Logger; @@ -31,7 +31,7 @@ namespace Umbraco.Web.UI.Controls /// Empty constructor, uses Singleton to resolve the UmbracoContext. /// protected UmbracoControl() - : this(Current.UmbracoContext, Current.Services, Current.ApplicationCache) + : this(Current.UmbracoContext, Current.Services) { } /// diff --git a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs index 5359592578..2a2aa43bb9 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs @@ -27,12 +27,11 @@ namespace Umbraco.Web.UI.Controls /// /// /// - /// - protected UmbracoUserControl(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) + protected UmbracoUserControl(UmbracoContext umbracoContext, ServiceContext services) { if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); UmbracoContext = umbracoContext; - Umbraco = new UmbracoHelper(umbracoContext, services, appCache); + Umbraco = new UmbracoHelper(umbracoContext, services); Members = new MembershipHelper(umbracoContext); // fixme inject somehow @@ -45,7 +44,7 @@ namespace Umbraco.Web.UI.Controls /// Empty constructor, uses Singleton to resolve the UmbracoContext /// protected UmbracoUserControl() - : this(Current.UmbracoContext, Current.Services, Current.ApplicationCache) + : this(Current.UmbracoContext, Current.Services) { } // for debugging purposes diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index c2f674f929..238edd877d 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -62,7 +62,7 @@ - + 2.6.2.25 @@ -151,6 +151,8 @@ + + @@ -159,6 +161,10 @@ + + + + @@ -215,7 +221,6 @@ - @@ -939,7 +944,7 @@ - + @@ -988,8 +993,7 @@ - - + diff --git a/src/Umbraco.Web/UmbracoAuthorizedHttpHandler.cs b/src/Umbraco.Web/UmbracoAuthorizedHttpHandler.cs index 42e3708d1c..1d8475111f 100644 --- a/src/Umbraco.Web/UmbracoAuthorizedHttpHandler.cs +++ b/src/Umbraco.Web/UmbracoAuthorizedHttpHandler.cs @@ -13,13 +13,11 @@ namespace Umbraco.Web protected UmbracoAuthorizedHttpHandler() { } - protected UmbracoAuthorizedHttpHandler(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) - : base(umbracoContext, services, appCache) + protected UmbracoAuthorizedHttpHandler(UmbracoContext umbracoContext, ServiceContext services) + : base(umbracoContext, services) { } - private bool _hasValidated = false; - /// /// Checks if the umbraco context id is valid /// diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index ea66ec13da..297f586ebe 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -30,13 +30,11 @@ namespace Umbraco.Web private readonly IPublishedContent _currentPage; private readonly IPublishedContentQuery _iQuery; private readonly ServiceContext _services; - private readonly CacheHelper _appCache; - + private IUmbracoComponentRenderer _componentRenderer; private IPublishedContentQuery _query; private MembershipHelper _membershipHelper; private ITagQuery _tag; - private IDataTypeService _dataTypeService; private ICultureDictionary _cultureDictionary; #region Constructors @@ -48,34 +46,21 @@ namespace Umbraco.Web internal UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content, IPublishedContentQuery query, ITagQuery tagQuery, - IDataTypeService dataTypeService, ICultureDictionary cultureDictionary, IUmbracoComponentRenderer componentRenderer, MembershipHelper membershipHelper, - ServiceContext services, - CacheHelper appCache) + ServiceContext services) { - if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); - if (content == null) throw new ArgumentNullException(nameof(content)); - if (query == null) throw new ArgumentNullException(nameof(query)); if (tagQuery == null) throw new ArgumentNullException(nameof(tagQuery)); - if (dataTypeService == null) throw new ArgumentNullException(nameof(dataTypeService)); - if (cultureDictionary == null) throw new ArgumentNullException(nameof(cultureDictionary)); - if (componentRenderer == null) throw new ArgumentNullException(nameof(componentRenderer)); - if (membershipHelper == null) throw new ArgumentNullException(nameof(membershipHelper)); - if (services == null) throw new ArgumentNullException(nameof(services)); - if (appCache == null) throw new ArgumentNullException(nameof(appCache)); - _umbracoContext = umbracoContext; + _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); _tag = tagQuery; - _dataTypeService = dataTypeService; - _cultureDictionary = cultureDictionary; - _componentRenderer = componentRenderer; - _membershipHelper = membershipHelper; - _currentPage = content; - _iQuery = query; - _services = services; - _appCache = appCache; + _cultureDictionary = cultureDictionary ?? throw new ArgumentNullException(nameof(cultureDictionary)); + _componentRenderer = componentRenderer ?? throw new ArgumentNullException(nameof(componentRenderer)); + _membershipHelper = membershipHelper ?? throw new ArgumentNullException(nameof(membershipHelper)); + _currentPage = content ?? throw new ArgumentNullException(nameof(content)); + _iQuery = query ?? throw new ArgumentNullException(nameof(query)); + _services = services ?? throw new ArgumentNullException(nameof(services)); } /// @@ -93,13 +78,11 @@ namespace Umbraco.Web /// An Umbraco context. /// A content item. /// A services context. - /// An application cache helper. /// Sets the current page to the supplied content item. - public UmbracoHelper(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache, IPublishedContent content) - : this(umbracoContext, services, appCache) + public UmbracoHelper(UmbracoContext umbracoContext, ServiceContext services, IPublishedContent content) + : this(umbracoContext, services) { - if (content == null) throw new ArgumentNullException(nameof(content)); - _currentPage = content; + _currentPage = content ?? throw new ArgumentNullException(nameof(content)); } /// @@ -107,19 +90,13 @@ namespace Umbraco.Web /// /// An Umbraco context. /// A services context. - /// An application cache helper. /// Sets the current page to the context's published content request's content item. - public UmbracoHelper(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) + public UmbracoHelper(UmbracoContext umbracoContext, ServiceContext services) { - if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); - if (services == null) throw new ArgumentNullException(nameof(services)); - if (appCache == null) throw new ArgumentNullException(nameof(appCache)); - - _umbracoContext = umbracoContext; + _services = services ?? throw new ArgumentNullException(nameof(services)); + _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); if (_umbracoContext.IsFrontEndUmbracoRequest) _currentPage = _umbracoContext.PublishedRequest.PublishedContent; - _services = services; - _appCache = appCache; } #endregion @@ -160,12 +137,6 @@ namespace Umbraco.Web /// public UrlProvider UrlProvider => UmbracoContext.UrlProvider; - /// - /// Gets the datatype service. - /// - private IDataTypeService DataTypeService => _dataTypeService - ?? (_dataTypeService = _services.DataTypeService); - /// /// Gets the component renderer. /// @@ -817,11 +788,11 @@ namespace Umbraco.Web /// /// /// - /// + /// /// - public IEnumerable Search(string term, bool useWildCards = true, string searchProvider = null) + public IEnumerable Search(string term, bool useWildCards = true, string indexName = null) { - return ContentQuery.Search(term, useWildCards, searchProvider); + return ContentQuery.Search(term, useWildCards, indexName); } /// @@ -832,11 +803,11 @@ namespace Umbraco.Web /// /// /// - /// + /// /// - public IEnumerable TypedSearch(int skip, int take, out int totalRecords, string term, bool useWildCards = true, string searchProvider = null) + public IEnumerable Search(int skip, int take, out long totalRecords, string term, bool useWildCards = true, string indexName = null) { - return ContentQuery.Search(skip, take, out totalRecords, term, useWildCards, searchProvider); + return ContentQuery.Search(skip, take, out totalRecords, term, useWildCards, indexName); } /// @@ -848,7 +819,7 @@ namespace Umbraco.Web /// /// /// - public IEnumerable TypedSearch(int skip, int take, out int totalRecords, Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null) + public IEnumerable Search(int skip, int take, out long totalRecords, Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null) { return ContentQuery.Search(skip, take, out totalRecords, criteria, searchProvider); } diff --git a/src/Umbraco.Web/UmbracoHttpHandler.cs b/src/Umbraco.Web/UmbracoHttpHandler.cs index e64c4c5fe1..e3a15faf24 100644 --- a/src/Umbraco.Web/UmbracoHttpHandler.cs +++ b/src/Umbraco.Web/UmbracoHttpHandler.cs @@ -17,14 +17,14 @@ namespace Umbraco.Web private UrlHelper _url; protected UmbracoHttpHandler() - : this(Current.UmbracoContext, Current.Services, Current.ApplicationCache) + : this(Current.UmbracoContext, Current.Services) { } - protected UmbracoHttpHandler(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) + protected UmbracoHttpHandler(UmbracoContext umbracoContext, ServiceContext services) { if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); UmbracoContext = umbracoContext; - Umbraco = new UmbracoHelper(umbracoContext, services, appCache); + Umbraco = new UmbracoHelper(umbracoContext, services); // fixme inject somehow Logger = Current.Logger; diff --git a/src/Umbraco.Web/UmbracoWebService.cs b/src/Umbraco.Web/UmbracoWebService.cs index 20db7208b5..95764e40a7 100644 --- a/src/Umbraco.Web/UmbracoWebService.cs +++ b/src/Umbraco.Web/UmbracoWebService.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web protected UmbracoWebService() { UmbracoContext = Current.UmbracoContext; - Umbraco = new UmbracoHelper(UmbracoContext, Current.Services, Current.ApplicationCache); + Umbraco = new UmbracoHelper(UmbracoContext, Current.Services); Logger = Current.Logger; ProfilingLogger = Current.ProfilingLogger; diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index eff5a9cee7..56cc884d39 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -95,7 +95,7 @@ namespace Umbraco.Web.WebApi /// Gets the Umbraco helper. /// public UmbracoHelper Umbraco => _umbracoHelper - ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services, ApplicationCache)); + ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services)); /// /// Gets the web security helper. diff --git a/src/Umbraco.Web/umbraco.presentation/item.cs b/src/Umbraco.Web/umbraco.presentation/item.cs index d15d3d33c1..74cfb9bf25 100644 --- a/src/Umbraco.Web/umbraco.presentation/item.cs +++ b/src/Umbraco.Web/umbraco.presentation/item.cs @@ -60,7 +60,7 @@ namespace umbraco if (_fieldName.StartsWith("#")) { - var umbHelper = new UmbracoHelper(Current.UmbracoContext, Current.Services, Current.ApplicationCache); + var umbHelper = new UmbracoHelper(Current.UmbracoContext, Current.Services); _fieldContent = umbHelper.GetDictionaryValue(_fieldName.Substring(1, _fieldName.Length - 1)); }