private async IAsyncEnumerable SearchDocumentsAsync( OrgSlug org, string? searchTerm, DocumentTypeSet documentTypes, bool includeUntypedDocuments, DocumentRelativePath? startAfter, [EnumeratorCancellation] CancellationToken cancellationToken) { var query = searchTerm?.Trim(); await foreach (var doc in ListDocumentsAsync(org, startAfter, cancellationToken)) { if (!doc.Type.MatchesFilter(documentTypes, includeUntypedDocuments)) continue; if (!String.IsNullOrEmpty(query) && !doc.Name.Matches(query)) continue; yield return doc; } } // Houston/Model/Documents/DocumentName.cs public bool Matches(string pattern) { return Value.Contains(pattern, StringComparison.CurrentCultureIgnoreCase); } // Houston/Model/Documents/DocumentType.cs public bool MatchesFilter(DocumentTypeSet documentTypes, bool includeUntypedDocuments) { if (documentTypes.IsEmpty && !includeUntypedDocuments) return true; if (documentType is null) return includeUntypedDocuments; return documentTypes.Types.Contains(documentType.Value); }