Skip to content

Commit ee64690

Browse files
committed
add api/pipelinesource and setup basic listen test
1 parent 422723a commit ee64690

13 files changed

+458
-60
lines changed

packages/firestore/.idea/runConfigurations/Integration_Tests__Emulator_w__Mock_Persistence_.xml

-19
This file was deleted.

packages/firestore/src/api/database.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import {
4646
connectFirestoreEmulator,
4747
Firestore as LiteFirestore
4848
} from '../lite-api/database';
49-
import { PipelineSource } from '../lite-api/pipeline-source';
49+
import { PipelineSource } from './pipeline_source';
5050
import { DocumentReference, Query } from '../lite-api/reference';
5151
import { newUserDataReader } from '../lite-api/user_data_reader';
5252
import {

packages/firestore/src/api/pipeline.ts

+36-13
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
import { Pipeline as LitePipeline } from '../lite-api/pipeline';
66
import { PipelineResult } from '../lite-api/pipeline-result';
77
import { DocumentData, DocumentReference } from '../lite-api/reference';
8-
import { AddFields, Stage } from '../lite-api/stage';
8+
import {AddFields, Sort, Stage, Where} from '../lite-api/stage';
99
import { UserDataReader } from '../lite-api/user_data_reader';
1010
import { AbstractUserDataWriter } from '../lite-api/user_data_writer';
1111
import { DocumentKey } from '../model/document_key';
@@ -15,6 +15,8 @@ import { DocumentSnapshot, PipelineSnapshot } from './snapshot';
1515
import { FirestoreError } from '../util/error';
1616
import { Unsubscribe } from './reference_impl';
1717
import { cast } from '../util/input_validation';
18+
import {Field, FilterCondition} from '../api';
19+
import {Expr} from '../lite-api/expressions';
1820

1921
export class Pipeline<
2022
AppModelType = DocumentData
@@ -49,6 +51,20 @@ export class Pipeline<
4951
);
5052
}
5153

54+
where(condition: FilterCondition & Expr): Pipeline<AppModelType> {
55+
const copy = this.stages.map(s => s);
56+
super.readUserData('where', condition);
57+
copy.push(new Where(condition));
58+
return new Pipeline(
59+
this.db,
60+
this.userDataReader,
61+
this.userDataWriter,
62+
this.documentReferenceFactory,
63+
copy,
64+
this.converter
65+
);
66+
}
67+
5268
/**
5369
* Executes this pipeline and returns a Promise to represent the asynchronous operation.
5470
*
@@ -106,23 +122,30 @@ export class Pipeline<
106122
* @internal
107123
* @private
108124
*/
109-
_onSnapshot(observer: {
110-
next?: (snapshot: PipelineSnapshot) => void;
111-
error?: (error: FirestoreError) => void;
112-
complete?: () => void;
113-
}): Unsubscribe {
125+
_onSnapshot(
126+
next: (snapshot: PipelineSnapshot) => void,
127+
error?: (error: FirestoreError) => void,
128+
complete?: () => void
129+
): Unsubscribe {
130+
// this.stages.push(
131+
// new AddFields(
132+
// this.selectablesToMap([
133+
// '__name__',
134+
// '__create_time__',
135+
// '__update_time__'
136+
// ])
137+
// )
138+
// );
139+
114140
this.stages.push(
115-
new AddFields(
116-
this.selectablesToMap([
117-
'__name__',
118-
'__create_time__',
119-
'__update_time__'
120-
])
141+
new Sort([
142+
Field.of('__name__').ascending()
143+
]
121144
)
122145
);
123146

124147
const client = ensureFirestoreConfigured(this.db);
125-
firestoreClientListenPipeline(client, this, observer);
148+
firestoreClientListenPipeline(client, this, {next, error, complete});
126149

127150
return () => {};
128151
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import { DocumentKey } from '../model/document_key';
16+
17+
import { Firestore } from './database';
18+
import { Pipeline } from './pipeline';
19+
import { DocumentReference } from './reference';
20+
import {
21+
CollectionGroupSource,
22+
CollectionSource,
23+
DatabaseSource,
24+
DocumentsSource
25+
} from '../lite-api/stage';
26+
import {PipelineSource as LitePipelineSource} from '../lite-api/pipeline-source';
27+
import { UserDataReader } from '../lite-api/user_data_reader';
28+
import { AbstractUserDataWriter } from '../lite-api/user_data_writer';
29+
30+
/**
31+
* Represents the source of a Firestore {@link Pipeline}.
32+
* @beta
33+
*/
34+
export class PipelineSource extends LitePipelineSource{
35+
/**
36+
* @internal
37+
* @private
38+
* @param db
39+
* @param userDataReader
40+
* @param userDataWriter
41+
* @param documentReferenceFactory
42+
*/
43+
constructor(
44+
db: Firestore,
45+
userDataReader: UserDataReader,
46+
userDataWriter: AbstractUserDataWriter,
47+
documentReferenceFactory: (id: DocumentKey) => DocumentReference
48+
) {
49+
super(db, userDataReader, userDataWriter, documentReferenceFactory);
50+
}
51+
52+
collection(collectionPath: string): Pipeline {
53+
return new Pipeline(
54+
this.db as Firestore,
55+
this.userDataReader,
56+
this.userDataWriter,
57+
this.documentReferenceFactory,
58+
[new CollectionSource(collectionPath)]
59+
);
60+
}
61+
62+
collectionGroup(collectionId: string): Pipeline {
63+
return new Pipeline(
64+
this.db as Firestore,
65+
this.userDataReader,
66+
this.userDataWriter,
67+
this.documentReferenceFactory,
68+
[new CollectionGroupSource(collectionId)]
69+
);
70+
}
71+
72+
database(): Pipeline {
73+
return new Pipeline(
74+
this.db as Firestore,
75+
this.userDataReader,
76+
this.userDataWriter,
77+
this.documentReferenceFactory,
78+
[new DatabaseSource()]
79+
);
80+
}
81+
82+
documents(docs: DocumentReference[]): Pipeline {
83+
return new Pipeline(
84+
this.db as Firestore,
85+
this.userDataReader,
86+
this.userDataWriter,
87+
this.documentReferenceFactory,
88+
[DocumentsSource.of(docs)]
89+
);
90+
}
91+
}

packages/firestore/src/core/sync_engine_impl.ts

+5
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,11 @@ function removeAndCleanupTarget(
999999
): void {
10001000
syncEngineImpl.sharedClientState.removeLocalQueryTarget(targetId);
10011001

1002+
// TODO(pipeline): REMOVE this hack.
1003+
if(!syncEngineImpl.queriesByTarget.has(targetId)||syncEngineImpl.queriesByTarget.get(targetId)!.length !== 0){
1004+
return;
1005+
}
1006+
10021007
debugAssert(
10031008
syncEngineImpl.queriesByTarget.has(targetId) &&
10041009
syncEngineImpl.queriesByTarget.get(targetId)!.length !== 0,

packages/firestore/src/lite-api/pipeline-source.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ export class PipelineSource {
4040
* @param documentReferenceFactory
4141
*/
4242
constructor(
43-
private db: Firestore,
44-
private userDataReader: UserDataReader,
45-
private userDataWriter: AbstractUserDataWriter,
46-
private documentReferenceFactory: (id: DocumentKey) => DocumentReference
43+
protected db: Firestore,
44+
protected userDataReader: UserDataReader,
45+
protected userDataWriter: AbstractUserDataWriter,
46+
protected documentReferenceFactory: (id: DocumentKey) => DocumentReference
4747
) {}
4848

4949
collection(collectionPath: string): Pipeline {

packages/firestore/src/lite-api/pipeline.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export class Pipeline<AppModelType = DocumentData> implements ProtoSerializable<
130130
*/
131131
constructor(
132132
private liteDb: Firestore,
133-
private userDataReader: UserDataReader,
133+
protected userDataReader: UserDataReader,
134134
/**
135135
* @internal
136136
* @private
@@ -144,7 +144,7 @@ export class Pipeline<AppModelType = DocumentData> implements ProtoSerializable<
144144
protected stages: Stage[],
145145
// TODO(pipeline) support converter
146146
//private converter: FirestorePipelineConverter<AppModelType> = defaultPipelineConverter()
147-
private converter: unknown = {}
147+
protected converter: unknown = {}
148148
) {}
149149

150150
/**
@@ -265,7 +265,7 @@ export class Pipeline<AppModelType = DocumentData> implements ProtoSerializable<
265265
* @return the expressionMap argument.
266266
* @private
267267
*/
268-
private readUserData<
268+
protected readUserData<
269269
T extends
270270
| Map<string, ReadableUserData>
271271
| ReadableUserData[]

packages/firestore/src/local/local_store_impl.ts

+7
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,13 @@ export async function localStoreReleaseTarget(
10501050
): Promise<void> {
10511051
const localStoreImpl = debugCast(localStore, LocalStoreImpl);
10521052
const targetData = localStoreImpl.targetDataByTarget.get(targetId);
1053+
1054+
// TODO(pipeline): this is a hack that only works because pipelines are the only ones returning nulls here.
1055+
// REMOVE ASAP.
1056+
if(targetData === null) {
1057+
return;
1058+
}
1059+
10531060
debugAssert(
10541061
targetData !== null,
10551062
`Tried to release nonexistent target: ${targetId}`

0 commit comments

Comments
 (0)