@@ -37,7 +37,7 @@ import {
3737 Timestamp as ProtoTimestamp ,
3838 Value as ProtoValue
3939} from '../protos/firestore_proto_api' ;
40- import { fail } from '../util/assert' ;
40+ import { debugAssert , fail } from '../util/assert' ;
4141import { isPlainObject } from '../util/input_validation' ;
4242
4343import {
@@ -47,7 +47,6 @@ import {
4747 Filter as FilterInternal ,
4848 Operator
4949} from './filter' ;
50- import { Pipeline } from '../lite-api/pipeline' ;
5150import {
5251 AddFields ,
5352 Aggregate ,
@@ -64,6 +63,15 @@ import {
6463 Stage ,
6564 Where
6665} from '../lite-api/stage' ;
66+ import { Pipeline } from '../api/pipeline' ;
67+ import { Pipeline as LitePipeline } from '../lite-api/pipeline' ;
68+ import { canonifyQuery , Query , queryEquals , stringifyQuery } from './query' ;
69+ import {
70+ canonifyTarget ,
71+ Target ,
72+ targetEquals ,
73+ targetIsPipelineTarget
74+ } from './target' ;
6775
6876/* eslint @typescript-eslint/no-explicit-any: 0 */
6977
@@ -357,12 +365,17 @@ function canonifyExprMap(map: Map<string, Expr>): string {
357365 . join ( ',' ) } `;
358366}
359367
360- export function canonifyPipeline ( p : Pipeline ) : string {
368+ export function canonifyPipeline ( p : LitePipeline ) : string ;
369+ export function canonifyPipeline ( p : Pipeline ) : string ;
370+ export function canonifyPipeline ( p : Pipeline | LitePipeline ) : string {
361371 return p . stages . map ( s => canonifyStage ( s ) ) . join ( '|' ) ;
362372}
363373
364374// TODO(pipeline): do a proper implementation for eq.
365- export function pipelineEq ( left : Pipeline , right : Pipeline ) : boolean {
375+ export function pipelineEq (
376+ left : Pipeline | LitePipeline ,
377+ right : Pipeline | LitePipeline
378+ ) : boolean {
366379 return canonifyPipeline ( left ) === canonifyPipeline ( right ) ;
367380}
368381
@@ -389,3 +402,120 @@ export function getPipelineFlavor(p: Pipeline): PipelineFlavor {
389402
390403 return flavor ;
391404}
405+
406+ export type PipelineSourceType =
407+ | 'collection'
408+ | 'collection-group'
409+ | 'database'
410+ | 'documents' ;
411+
412+ export function getPipelineSourceType (
413+ p : Pipeline
414+ ) : PipelineSourceType | 'unknown' {
415+ debugAssert ( p . stages . length > 0 , 'Pipeline must have at least one stage' ) ;
416+ const source = p . stages [ 0 ] ;
417+
418+ if (
419+ source . name === CollectionSource . name ||
420+ source . name === CollectionGroupSource . name ||
421+ source . name === DatabaseSource . name ||
422+ source . name === DocumentsSource . name
423+ ) {
424+ return source . name as PipelineSourceType ;
425+ }
426+
427+ return 'unknown' ;
428+ }
429+
430+ export function getPipelineCollection ( p : Pipeline ) : string | undefined {
431+ if ( getPipelineSourceType ( p ) === 'collection' ) {
432+ return ( p . stages [ 0 ] as CollectionSource ) . collectionPath ;
433+ }
434+ return undefined ;
435+ }
436+
437+ export function getPipelineCollectionGroup ( p : Pipeline ) : string | undefined {
438+ if ( getPipelineSourceType ( p ) === 'collection-group' ) {
439+ return ( p . stages [ 0 ] as CollectionGroupSource ) . collectionId ;
440+ }
441+ return undefined ;
442+ }
443+
444+ export function getPipelineDocuments ( p : Pipeline ) : string [ ] | undefined {
445+ if ( getPipelineSourceType ( p ) === 'documents' ) {
446+ return ( p . stages [ 0 ] as DocumentsSource ) . docPaths ;
447+ }
448+ return undefined ;
449+ }
450+
451+ export type QueryOrPipeline = Query | Pipeline ;
452+
453+ export function isPipeline ( q : QueryOrPipeline ) : q is Pipeline {
454+ return q instanceof Pipeline ;
455+ }
456+
457+ export function stringifyQueryOrPipeline ( q : QueryOrPipeline ) : string {
458+ if ( isPipeline ( q ) ) {
459+ return canonifyPipeline ( q ) ;
460+ }
461+
462+ return stringifyQuery ( q ) ;
463+ }
464+
465+ export function canonifyQueryOrPipeline ( q : QueryOrPipeline ) : string {
466+ if ( isPipeline ( q ) ) {
467+ return canonifyPipeline ( q ) ;
468+ }
469+
470+ return canonifyQuery ( q ) ;
471+ }
472+
473+ export function queryOrPipelineEqual (
474+ left : QueryOrPipeline ,
475+ right : QueryOrPipeline
476+ ) : boolean {
477+ if ( left instanceof Pipeline && right instanceof Pipeline ) {
478+ return pipelineEq ( left , right ) ;
479+ }
480+ if (
481+ ( left instanceof Pipeline && ! ( right instanceof Pipeline ) ) ||
482+ ( ! ( left instanceof Pipeline ) && right instanceof Pipeline )
483+ ) {
484+ return false ;
485+ }
486+
487+ return queryEquals ( left as Query , right as Query ) ;
488+ }
489+
490+ export type TargetOrPipeline = Target | Pipeline ;
491+
492+ export function canonifyTargetOrPipeline ( q : TargetOrPipeline ) : string {
493+ if ( targetIsPipelineTarget ( q ) ) {
494+ return canonifyPipeline ( q ) ;
495+ }
496+
497+ return canonifyTarget ( q as Target ) ;
498+ }
499+
500+ export function targetOrPipelineEqual (
501+ left : TargetOrPipeline ,
502+ right : TargetOrPipeline
503+ ) : boolean {
504+ if ( left instanceof Pipeline && right instanceof Pipeline ) {
505+ return pipelineEq ( left , right ) ;
506+ }
507+ if (
508+ ( left instanceof Pipeline && ! ( right instanceof Pipeline ) ) ||
509+ ( ! ( left instanceof Pipeline ) && right instanceof Pipeline )
510+ ) {
511+ return false ;
512+ }
513+
514+ return targetEquals ( left as Target , right as Target ) ;
515+ }
516+
517+ export function pipelineHasRanges ( pipeline : Pipeline ) : boolean {
518+ return pipeline . stages . some (
519+ stage => stage . name === Limit . name || stage . name === Offset . name
520+ ) ;
521+ }
0 commit comments