diff --git a/src/search/backend.tsx b/src/search/backend.tsx index c8fba06bd0dc..8cd02c34c37d 100644 --- a/src/search/backend.tsx +++ b/src/search/backend.tsx @@ -1,151 +1,163 @@ import { isEqual } from 'lodash' import { Observable } from 'rxjs' -import { distinctUntilChanged, map, mergeMap } from 'rxjs/operators' +import { catchError, distinctUntilChanged, map, mergeMap, switchMap } from 'rxjs/operators' import { SearchOptions } from '.' import { gql, queryGraphQL } from '../backend/graphql' import * as GQL from '../backend/graphqlschema' import { mutateConfigurationGraphQL } from '../configuration/backend' +import { ExtensionsControllerProps } from '../extensions/ExtensionsClientCommonContext' import { currentConfiguration } from '../settings/configuration' -import { createAggregateError } from '../util/errors' +import { asError, createAggregateError, ErrorLike } from '../util/errors' -export function search(options: SearchOptions): Observable { - return queryGraphQL( - gql` - query Search($query: String!) { - search(query: $query) { - results { - __typename - limitHit - resultCount - approximateResultCount - missing { - name - } - cloning { - name - } - timedout { - name - } - indexUnavailable - dynamicFilters { - value - label - count - limitHit - kind - } - results { - ... on Repository { +export function search( + options: SearchOptions, + { extensionsController }: ExtensionsControllerProps +): Observable { + /** + * Emits whenever a search is executed, and whenever an extension registers a query transformer. + */ + return extensionsController.registries.queryTransformer.transformQuery(options.query).pipe( + switchMap(query => + queryGraphQL( + gql` + query Search($query: String!) { + search(query: $query) { + results { __typename - id - name - url - } - ... on FileMatch { - __typename - file { - path - url - commit { - oid - } - } - repository { - name - url - } limitHit - symbols { + resultCount + approximateResultCount + missing { name - containerName - url - kind - } - lineMatches { - preview - lineNumber - offsetAndLengths } - } - ... on CommitSearchResult { - __typename - refs { + cloning { name - displayName - prefix - repository { - name - } } - sourceRefs { + timedout { name - displayName - prefix - repository { - name - } - } - messagePreview { - value - highlights { - line - character - length - } } - diffPreview { + indexUnavailable + dynamicFilters { value - highlights { - line - character - length - } + label + count + limitHit + kind } - commit { - id - repository { + results { + ... on Repository { + __typename + id name url } - oid - abbreviatedOID - author { - person { + ... on FileMatch { + __typename + file { + path + url + commit { + oid + } + } + repository { + name + url + } + limitHit + symbols { + name + containerName + url + kind + } + lineMatches { + preview + lineNumber + offsetAndLengths + } + } + ... on CommitSearchResult { + __typename + refs { + name displayName - avatarURL + prefix + repository { + name + } + } + sourceRefs { + name + displayName + prefix + repository { + name + } + } + messagePreview { + value + highlights { + line + character + length + } + } + diffPreview { + value + highlights { + line + character + length + } + } + commit { + id + repository { + name + url + } + oid + abbreviatedOID + author { + person { + displayName + avatarURL + } + date + } + message + url + tree(path: "") { + canonicalURL + } } - date } - message - url - tree(path: "") { - canonicalURL + } + alert { + title + description + proposedQueries { + description + query } } + elapsedMilliseconds } } - alert { - title - description - proposedQueries { - description - query - } - } - elapsedMilliseconds } - } - } - `, - { query: options.query } - ).pipe( - map(({ data, errors }) => { - if (!data || !data.search || !data.search.results) { - throw createAggregateError(errors) - } - return data.search.results - }) + `, + { query } + ).pipe( + map(({ data, errors }) => { + if (!data || !data.search || !data.search.results) { + throw createAggregateError(errors) + } + return data.search.results + }), + catchError(error => [asError(error)]) + ) + ) ) } diff --git a/src/search/results/SearchResults.tsx b/src/search/results/SearchResults.tsx index 78fb5fb8d807..ed21cc4b5597 100644 --- a/src/search/results/SearchResults.tsx +++ b/src/search/results/SearchResults.tsx @@ -6,8 +6,10 @@ import { catchError, distinctUntilChanged, filter, map, startWith, switchMap, ta import { parseSearchURLQuery, SearchOptions } from '..' import * as GQL from '../../backend/graphqlschema' import { PageTitle } from '../../components/PageTitle' +import { ExtensionsControllerProps } from '../../extensions/ExtensionsClientCommonContext' import { currentConfiguration } from '../../settings/configuration' import { eventLogger } from '../../tracking/eventLogger' +import { isErrorLike } from '../../util/errors' import { search } from '../backend' import { FilterChip } from '../FilterChip' import { isSearchResults, submitSearch, toggleSearchFilter } from '../helpers' @@ -17,7 +19,7 @@ import { SearchResultsListOld } from './SearchResultsListOld' const UI_PAGE_SIZE = 75 -interface SearchResultsProps { +interface SearchResultsProps extends ExtensionsControllerProps { authenticatedUser: GQL.IUser | null location: H.Location history: H.History @@ -87,7 +89,7 @@ export class SearchResults extends React.Component @@ -95,8 +97,10 @@ export class SearchResults extends React.Component 0, + results_count: isErrorLike(results) ? 0 : results.results.length, + any_cloning: isErrorLike(results) + ? false + : results.cloning.length > 0, }, }, }),