Skip to content

Commit 7a3e789

Browse files
committed
type1 compiles
1 parent 82b8303 commit 7a3e789

27 files changed

+724
-277
lines changed

packages/firestore/src/api/pipeline.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ import { AbstractUserDataWriter } from '../lite-api/user_data_writer';
1111
import { DocumentKey } from '../model/document_key';
1212

1313
import { ensureFirestoreConfigured, Firestore } from './database';
14-
import { DocumentSnapshot, PipelineSnapshot } from './snapshot';
14+
import { DocumentSnapshot, PipelineSnapshot, QuerySnapshot } from './snapshot';
1515
import { FirestoreError } from '../util/error';
1616
import { Unsubscribe } from './reference_impl';
1717
import { cast } from '../util/input_validation';
1818
import { Field, FilterCondition } from '../api';
1919
import { Expr } from '../lite-api/expressions';
20+
import { CompleteFn, ErrorFn, NextFn } from './observer';
21+
import { ViewSnapshot } from '../core/view_snapshot';
2022

2123
export class Pipeline<
2224
AppModelType = DocumentData
@@ -140,6 +142,13 @@ export class Pipeline<
140142
this.stages.push(new Sort([Field.of('__name__').ascending()]));
141143

142144
const client = ensureFirestoreConfigured(this.db);
145+
const observer = {
146+
next: (snapshot: ViewSnapshot) => {
147+
new PipelineSnapshot(this, snapshot);
148+
},
149+
error: error,
150+
complete: complete
151+
};
143152
// TODO(pipeline) hook up options
144153
firestoreClientListen(client, this, {}, observer);
145154

packages/firestore/src/api/snapshot.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ import { Code, FirestoreError } from '../util/error';
4141
import { Firestore } from './database';
4242
import { SnapshotListenOptions } from './reference_impl';
4343
import { Pipeline } from './pipeline';
44-
import { PipelineResult } from '../lite-api/pipeline-result';
44+
import { PipelineResult, toPipelineResult } from '../lite-api/pipeline-result';
45+
import { isPipeline } from '../core/pipeline-util';
46+
import { newPipelineComparator } from '../core/pipeline_run';
4547

4648
/**
4749
* Converter used by `withConverter()` to transform user objects of type
@@ -673,12 +675,11 @@ export function changesFromSnapshot<
673675
change.type === ChangeType.Added,
674676
'Invalid event type for first snapshot'
675677
);
678+
const comparator = isPipeline(querySnapshot._snapshot.query)
679+
? newPipelineComparator(querySnapshot._snapshot.query)
680+
: newQueryComparator(querySnapshot.query._query);
676681
debugAssert(
677-
!lastDoc ||
678-
newQueryComparator(querySnapshot._snapshot.query)(
679-
lastDoc,
680-
change.doc
681-
) < 0,
682+
!lastDoc || comparator(lastDoc, change.doc) < 0,
682683
'Got added events in wrong order'
683684
);
684685
const doc = new QueryDocumentSnapshot<AppModelType, DbModelType>(
@@ -800,16 +801,30 @@ export class PipelineSnapshot<AppModelType = DocumentData> {
800801
*/
801802
readonly pipeline: Pipeline<AppModelType>;
802803

804+
/**
805+
* Metadata about this snapshot, concerning its source and if it has local
806+
* modifications.
807+
*/
808+
readonly metadata: SnapshotMetadata;
809+
803810
/** @hideconstructor */
804811
constructor(
805812
pipeline: Pipeline<AppModelType>,
806-
readonly _snapshot: PipelineResult<AppModelType>[]
813+
readonly _snapshot: ViewSnapshot
807814
) {
815+
this.metadata = new SnapshotMetadata(
816+
_snapshot.hasPendingWrites,
817+
_snapshot.fromCache
818+
);
808819
this.pipeline = pipeline;
809820
}
810821

811822
/** An array of all the documents in the `QuerySnapshot`. */
812823
get results(): Array<PipelineResult<AppModelType>> {
813-
return this._snapshot;
824+
const result: Array<PipelineResult<AppModelType>> = [];
825+
this._snapshot.docs.forEach(doc =>
826+
result.push(toPipelineResult(doc, this.pipeline))
827+
);
828+
return result;
814829
}
815830
}

packages/firestore/src/core/event_manager.ts

Lines changed: 8 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@ import { Code, FirestoreError } from '../util/error';
2121
import { EventHandler } from '../util/misc';
2222
import { ObjectMap } from '../util/obj_map';
2323

24-
import { canonifyQuery, Query, queryEquals, stringifyQuery } from './query';
24+
import { Query, stringifyQuery } from './query';
2525
import { OnlineState } from './types';
2626
import { ChangeType, DocumentViewChange, ViewSnapshot } from './view_snapshot';
2727
import { Pipeline } from '../api/pipeline';
2828
import { PipelineSnapshot } from '../api/snapshot';
29-
import { PipelineResultView } from './sync_engine_impl';
30-
import { canonifyPipeline, pipelineEq } from './pipeline-util';
29+
import {
30+
canonifyPipeline,
31+
canonifyQueryOrPipeline,
32+
isPipeline,
33+
QueryOrPipeline,
34+
queryOrPipelineEqual
35+
} from './pipeline-util';
3136

3237
/**
3338
* Holds the listeners and the last received ViewSnapshot for a query being
@@ -51,12 +56,6 @@ export interface Observer<T> {
5156
error: EventHandler<FirestoreError>;
5257
}
5358

54-
export type QueryOrPipeline = Query | Pipeline;
55-
56-
export function isPipeline(q: QueryOrPipeline): q is Pipeline {
57-
return q instanceof Pipeline;
58-
}
59-
6059
/**
6160
* EventManager is responsible for mapping queries to query event emitters.
6261
* It handles "fan-out". -- Identical queries will re-use the same watch on the
@@ -122,39 +121,6 @@ export class EventManagerImpl implements EventManager {
122121
}
123122
}
124123

125-
export function stringifyQueryOrPipeline(q: QueryOrPipeline): string {
126-
if (isPipeline(q)) {
127-
return canonifyPipeline(q);
128-
}
129-
130-
return stringifyQuery(q);
131-
}
132-
133-
export function canonifyQueryOrPipeline(q: QueryOrPipeline): string {
134-
if (isPipeline(q)) {
135-
return canonifyPipeline(q);
136-
}
137-
138-
return canonifyQuery(q);
139-
}
140-
141-
export function queryOrPipelineEqual(
142-
left: QueryOrPipeline,
143-
right: QueryOrPipeline
144-
): boolean {
145-
if (left instanceof Pipeline && right instanceof Pipeline) {
146-
return pipelineEq(left, right);
147-
}
148-
if (
149-
(left instanceof Pipeline && !(right instanceof Pipeline)) ||
150-
(!(left instanceof Pipeline) && right instanceof Pipeline)
151-
) {
152-
return false;
153-
}
154-
155-
return queryEquals(left as Query, right as Query);
156-
}
157-
158124
function newQueriesObjectMap(): ObjectMap<QueryOrPipeline, QueryListenersInfo> {
159125
return new ObjectMap<QueryOrPipeline, QueryListenersInfo>(
160126
q => canonifyQueryOrPipeline(q),
@@ -621,22 +587,3 @@ export class QueryListener {
621587
return this.options.source !== ListenerDataSource.Cache;
622588
}
623589
}
624-
625-
export class PipelineListener {
626-
private view: PipelineResultView | null = null;
627-
628-
constructor(
629-
readonly pipeline: Pipeline,
630-
private queryObserver: Observer<PipelineSnapshot>
631-
) {}
632-
633-
onViewSnapshot(view: PipelineResultView): boolean {
634-
this.view = view;
635-
this.queryObserver.next(view.toPipelineSnapshot());
636-
return true;
637-
}
638-
639-
onError(error: FirestoreError): void {
640-
this.queryObserver.error(error);
641-
}
642-
}

packages/firestore/src/core/firestore_client.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,12 @@ import {
8484
ListenOptions,
8585
Observer,
8686
QueryListener,
87-
QueryOrPipeline,
8887
removeSnapshotsInSyncListener
8988
} from './event_manager';
9089
import { newQueryForPath, Query } from './query';
9190
import { SyncEngine } from './sync_engine';
9291
import {
9392
syncEngineListen,
94-
syncEngineListenPipeline,
9593
syncEngineLoadBundle,
9694
syncEngineRegisterPendingWritesCallback,
9795
syncEngineUnlisten,
@@ -106,6 +104,7 @@ import { View } from './view';
106104
import { ViewSnapshot } from './view_snapshot';
107105
import { Unsubscribe } from '../api/reference_impl';
108106
import { PipelineSnapshot } from '../api/snapshot';
107+
import { QueryOrPipeline } from './pipeline-util';
109108

110109
const LOG_TAG = 'FirestoreClient';
111110
export const MAX_CONCURRENT_LIMBO_RESOLUTIONS = 100;

packages/firestore/src/core/pipeline-util.ts

Lines changed: 134 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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';
4141
import { isPlainObject } from '../util/input_validation';
4242

4343
import {
@@ -47,7 +47,6 @@ import {
4747
Filter as FilterInternal,
4848
Operator
4949
} from './filter';
50-
import { Pipeline } from '../lite-api/pipeline';
5150
import {
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

Comments
 (0)