Skip to content

Commit 5e43cd8

Browse files
committed
Merge remote-tracking branch 'origin/master' into TargetPurposeStringEnumValues_PR7257
2 parents ae3e211 + 510c9b5 commit 5e43cd8

File tree

12 files changed

+142
-115
lines changed

12 files changed

+142
-115
lines changed

.changeset/olive-goats-greet.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/firestore": patch
3+
---
4+
5+
Simplified the internal handling of aggregation results.

README.md

+14-7
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Please see [Environment Support](https://firebase.google.com/support/guides/envi
2929
#### Node.js
3030

3131
Before you can start working on the Firebase JS SDK, you need to have Node.js
32-
installed on your machine. The currently supported versions are `10.15.0` or greater.
32+
installed on your machine. The currently supported versions are `10.15.0` through `16.6.0`.
3333

3434
To download Node.js visit https://nodejs.org/en/download/.
3535

@@ -43,9 +43,14 @@ In addition to Node.js we use `yarn` to facilitate multi package development.
4343
To install `yarn` follow the instructions listed on their website:
4444
https://yarnpkg.com/en/docs/install
4545

46+
This repo currently supports building with yarn `1.x`. For instance, after installating yarn, run
47+
```bash
48+
$ yarn set version 1.22.11`
49+
```
50+
4651
#### Java
4752

48-
The closure compiler requires a modern Java installation. Java 8+ should be installed: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
53+
The closure compiler requires a modern Java installation. Java 11+ should be installed: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
4954

5055
#### Verify Prerequisites
5156

@@ -57,8 +62,8 @@ $ yarn -v
5762
$ java -version
5863
```
5964

60-
Your Node.js version should be `10.15.0` or greater, your `yarn` version should
61-
be `1.0.0` or greater, and your `java` version should be `1.8.0` or greater.
65+
Your `node` version should be between `10.15.0` and `16.6.0`, your `yarn` version should
66+
be between `1.0.0` and `1.22.11`, and your `java` version should be `11.0` or greater.
6267

6368
_NOTE: We will update the documentation as new versions are required, however
6469
for continuing development on the SDK, staying up to date on the stable versions
@@ -109,7 +114,7 @@ will be overwritten below.
109114
110115
Visit the "Realtime Database" section of the console and create a realtime
111116
database. When prompted to select the set of initial security rules, select
112-
any option (e.g. "Start in Production Mode") since these permission settings
117+
any option (e.g. "Start in Locked Mode") since these permission settings
113118
will be overwritten below.
114119
115120
#### Storage Setup
@@ -127,8 +132,10 @@ order to run the tests, you will need to update your bucket's CORS rules.
127132
}
128133
]
129134
```
130-
2. Install `gsutil` from https://cloud.google.com/storage/docs/gsutil_install
131-
3. Run `gsutil cors set cors.json gs://<your-cloud-storage-bucket>`
135+
1. Install `gsutil` from https://cloud.google.com/storage/docs/gsutil_install
136+
1. You will need to login if this is your first time using `gsutil`. Run `gcloud auth login`
137+
and follow the instructions to login.
138+
1. Run `gsutil cors set cors.json gs://<your-cloud-storage-bucket>`
132139
133140
For more information, visit https://firebase.google.com/docs/storage/web/download-files#cors_configuration
134141

packages/firestore/src/api/aggregate.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ import { AggregateImpl } from '../core/aggregate';
2020
import { firestoreClientRunAggregateQuery } from '../core/firestore_client';
2121
import { count } from '../lite-api/aggregate';
2222
import { AggregateQuerySnapshot } from '../lite-api/aggregate_types';
23-
import { AggregateAlias } from '../model/aggregate_alias';
24-
import { ObjectValue } from '../model/object_value';
23+
import { ApiClientObjectMap, Value } from '../protos/firestore_proto_api';
2524
import { cast } from '../util/input_validation';
2625
import { mapToArray } from '../util/obj';
2726

@@ -110,7 +109,7 @@ export function getAggregateFromServer<T extends AggregateSpec>(
110109

111110
const internalAggregates = mapToArray(aggregateSpec, (aggregate, alias) => {
112111
return new AggregateImpl(
113-
new AggregateAlias(alias),
112+
alias,
114113
aggregate._aggregateType,
115114
aggregate._internalFieldPath
116115
);
@@ -136,7 +135,7 @@ export function getAggregateFromServer<T extends AggregateSpec>(
136135
function convertToAggregateQuerySnapshot<T extends AggregateSpec>(
137136
firestore: Firestore,
138137
query: Query<unknown>,
139-
aggregateResult: ObjectValue
138+
aggregateResult: ApiClientObjectMap<Value>
140139
): AggregateQuerySnapshot<T> {
141140
const userDataWriter = new ExpUserDataWriter(firestore);
142141
const querySnapshot = new AggregateQuerySnapshot<T>(

packages/firestore/src/core/aggregate.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { AggregateAlias } from '../model/aggregate_alias';
1918
import { FieldPath } from '../model/path';
2019

2120
/**
@@ -29,7 +28,7 @@ export type AggregateType = 'count' | 'avg' | 'sum';
2928
*/
3029
export interface Aggregate {
3130
readonly fieldPath?: FieldPath;
32-
readonly alias: AggregateAlias;
31+
readonly alias: string;
3332
readonly aggregateType: AggregateType;
3433
}
3534

@@ -38,7 +37,7 @@ export interface Aggregate {
3837
*/
3938
export class AggregateImpl implements Aggregate {
4039
constructor(
41-
readonly alias: AggregateAlias,
40+
readonly alias: string,
4241
readonly aggregateType: AggregateType,
4342
readonly fieldPath?: FieldPath
4443
) {}

packages/firestore/src/core/firestore_client.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ import { Document } from '../model/document';
3636
import { DocumentKey } from '../model/document_key';
3737
import { FieldIndex } from '../model/field_index';
3838
import { Mutation } from '../model/mutation';
39-
import { ObjectValue } from '../model/object_value';
4039
import { toByteStreamReader } from '../platform/byte_stream_reader';
4140
import { newSerializer } from '../platform/serializer';
4241
import { newTextEncoder } from '../platform/text_serializer';
42+
import { ApiClientObjectMap, Value } from '../protos/firestore_proto_api';
4343
import { Datastore, invokeRunAggregationQueryRpc } from '../remote/datastore';
4444
import {
4545
RemoteStore,
@@ -526,8 +526,8 @@ export function firestoreClientRunAggregateQuery(
526526
client: FirestoreClient,
527527
query: Query,
528528
aggregates: Aggregate[]
529-
): Promise<ObjectValue> {
530-
const deferred = new Deferred<ObjectValue>();
529+
): Promise<ApiClientObjectMap<Value>> {
530+
const deferred = new Deferred<ApiClientObjectMap<Value>>();
531531

532532
client.asyncQueue.enqueueAndForget(async () => {
533533
// TODO (sum/avg) should we update this to use the event manager?

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

+3-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
import { deepEqual } from '@firebase/util';
1919

2020
import { AggregateImpl } from '../core/aggregate';
21-
import { AggregateAlias } from '../model/aggregate_alias';
22-
import { ObjectValue } from '../model/object_value';
21+
import { ApiClientObjectMap, Value } from '../protos/firestore_proto_api';
2322
import { invokeRunAggregationQueryRpc } from '../remote/datastore';
2423
import { cast } from '../util/input_validation';
2524
import { mapToArray } from '../util/obj';
@@ -96,7 +95,7 @@ export function getAggregate<T extends AggregateSpec>(
9695

9796
const internalAggregates = mapToArray(aggregateSpec, (aggregate, alias) => {
9897
return new AggregateImpl(
99-
new AggregateAlias(alias),
98+
alias,
10099
aggregate._aggregateType,
101100
aggregate._internalFieldPath
102101
);
@@ -115,7 +114,7 @@ export function getAggregate<T extends AggregateSpec>(
115114
function convertToAggregateQuerySnapshot<T extends AggregateSpec>(
116115
firestore: Firestore,
117116
query: Query<unknown>,
118-
aggregateResult: ObjectValue
117+
aggregateResult: ApiClientObjectMap<Value>
119118
): AggregateQuerySnapshot<T> {
120119
const userDataWriter = new LiteUserDataWriter(firestore);
121120
const querySnapshot = new AggregateQuerySnapshot<T>(

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
*/
1717

1818
import { AggregateType } from '../core/aggregate';
19-
import { ObjectValue } from '../model/object_value';
2019
import { FieldPath as InternalFieldPath } from '../model/path';
20+
import { ApiClientObjectMap, Value } from '../protos/firestore_proto_api';
2121

2222
import { Query } from './reference';
2323
import { AbstractUserDataWriter } from './user_data_writer';
@@ -85,7 +85,7 @@ export class AggregateQuerySnapshot<T extends AggregateSpec> {
8585
constructor(
8686
query: Query<unknown>,
8787
private readonly _userDataWriter: AbstractUserDataWriter,
88-
private readonly _data: ObjectValue
88+
private readonly _data: ApiClientObjectMap<Value>
8989
) {
9090
this.query = query;
9191
}
@@ -102,8 +102,8 @@ export class AggregateQuerySnapshot<T extends AggregateSpec> {
102102
* query.
103103
*/
104104
data(): AggregateSpecData<T> {
105-
return this._userDataWriter.convertValue(
106-
this._data.value
105+
return this._userDataWriter.convertObjectMap(
106+
this._data
107107
) as AggregateSpecData<T>;
108108
}
109109
}

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

+13-1
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ import {
3232
import { TypeOrder } from '../model/type_order';
3333
import { typeOrder } from '../model/values';
3434
import {
35+
ApiClientObjectMap,
3536
ArrayValue as ProtoArrayValue,
3637
LatLng as ProtoLatLng,
3738
MapValue as ProtoMapValue,
3839
Timestamp as ProtoTimestamp,
40+
Value,
3941
Value as ProtoValue
4042
} from '../protos/firestore_proto_api';
4143
import { isValidResourceName } from '../remote/serializer';
@@ -91,9 +93,19 @@ export abstract class AbstractUserDataWriter {
9193
private convertObject(
9294
mapValue: ProtoMapValue,
9395
serverTimestampBehavior: ServerTimestampBehavior
96+
): DocumentData {
97+
return this.convertObjectMap(mapValue.fields, serverTimestampBehavior);
98+
}
99+
100+
/**
101+
* @internal
102+
*/
103+
convertObjectMap(
104+
fields: ApiClientObjectMap<Value> | undefined,
105+
serverTimestampBehavior: ServerTimestampBehavior = 'none'
94106
): DocumentData {
95107
const result: DocumentData = {};
96-
forEach(mapValue.fields, (key, value) => {
108+
forEach(fields, (key, value) => {
97109
result[key] = this.convertValue(value, serverTimestampBehavior);
98110
});
99111
return result;

packages/firestore/src/model/aggregate_alias.ts

-48
This file was deleted.

packages/firestore/src/remote/datastore.ts

+31-7
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,20 @@ import { Query, queryToTarget } from '../core/query';
2222
import { Document } from '../model/document';
2323
import { DocumentKey } from '../model/document_key';
2424
import { Mutation } from '../model/mutation';
25-
import { ObjectValue } from '../model/object_value';
2625
import {
26+
ApiClientObjectMap,
2727
BatchGetDocumentsRequest as ProtoBatchGetDocumentsRequest,
2828
BatchGetDocumentsResponse as ProtoBatchGetDocumentsResponse,
2929
RunAggregationQueryRequest as ProtoRunAggregationQueryRequest,
3030
RunAggregationQueryResponse as ProtoRunAggregationQueryResponse,
3131
RunQueryRequest as ProtoRunQueryRequest,
32-
RunQueryResponse as ProtoRunQueryResponse
32+
RunQueryResponse as ProtoRunQueryResponse,
33+
Value
3334
} from '../protos/firestore_proto_api';
3435
import { debugAssert, debugCast, hardAssert } from '../util/assert';
3536
import { AsyncQueue } from '../util/async_queue';
3637
import { Code, FirestoreError } from '../util/error';
38+
import { isNullOrUndefined } from '../util/types';
3739

3840
import { Connection } from './connection';
3941
import {
@@ -50,8 +52,7 @@ import {
5052
toMutation,
5153
toName,
5254
toQueryTarget,
53-
toRunAggregationQueryRequest,
54-
fromAggregationResult
55+
toRunAggregationQueryRequest
5556
} from './serializer';
5657

5758
/**
@@ -243,9 +244,9 @@ export async function invokeRunAggregationQueryRpc(
243244
datastore: Datastore,
244245
query: Query,
245246
aggregates: Aggregate[]
246-
): Promise<ObjectValue> {
247+
): Promise<ApiClientObjectMap<Value>> {
247248
const datastoreImpl = debugCast(datastore, DatastoreImpl);
248-
const request = toRunAggregationQueryRequest(
249+
const { request, aliasMap } = toRunAggregationQueryRequest(
249250
datastoreImpl.serializer,
250251
queryToTarget(query),
251252
aggregates
@@ -267,8 +268,31 @@ export async function invokeRunAggregationQueryRpc(
267268
filteredResult.length === 1,
268269
'Aggregation fields are missing from result.'
269270
);
271+
debugAssert(
272+
!isNullOrUndefined(filteredResult[0].result),
273+
'aggregationQueryResponse.result'
274+
);
275+
debugAssert(
276+
!isNullOrUndefined(filteredResult[0].result.aggregateFields),
277+
'aggregationQueryResponse.result.aggregateFields'
278+
);
279+
280+
// Remap the short-form aliases that were sent to the server
281+
// to the client-side aliases. Users will access the results
282+
// using the client-side alias.
283+
const unmappedAggregateFields = filteredResult[0].result?.aggregateFields;
284+
const remappedFields = Object.keys(unmappedAggregateFields).reduce<
285+
ApiClientObjectMap<Value>
286+
>((accumulator, key) => {
287+
debugAssert(
288+
!isNullOrUndefined(aliasMap[key]),
289+
`'${key}' not present in aliasMap result`
290+
);
291+
accumulator[aliasMap[key]] = unmappedAggregateFields[key]!;
292+
return accumulator;
293+
}, {});
270294

271-
return fromAggregationResult(filteredResult[0]);
295+
return remappedFields;
272296
}
273297

274298
export function newPersistentWriteStream(

0 commit comments

Comments
 (0)