Skip to content

Commit

Permalink
[internal] Query/AggregateQuery to proto representation (#8177)
Browse files Browse the repository at this point in the history
* WIP: [internal] Query/AggregateQuery to proto representation.

* using api classes.

* move to a separate file.

* Only return the QueryTarget object.

* declare interface to avoid minification.

* lint fix.

* attempt to avoid minification of ToRunAggregationQueryRequestReturnType.

* allow skipping aliasing.
  • Loading branch information
ehsannas committed May 2, 2024
1 parent 14f9da6 commit f25b9e5
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 2 deletions.
4 changes: 4 additions & 0 deletions packages/firestore/src/api.ts
Expand Up @@ -219,6 +219,10 @@ export {
*/
export { isBase64Available as _isBase64Available } from './platform/base64';
export { DatabaseId as _DatabaseId } from './core/database_info';
export {
_internalQueryToProtoQueryTarget,
_internalAggregationQueryToProtoRunAggregationQueryRequest
} from './remote/internal_serializer';
export {
cast as _cast,
validateIsNotUsedTogether as _validateIsNotUsedTogether
Expand Down
89 changes: 89 additions & 0 deletions packages/firestore/src/remote/internal_serializer.ts
@@ -0,0 +1,89 @@
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { ensureFirestoreConfigured, Firestore } from '../api/database';
import { AggregateImpl } from '../core/aggregate';
import { queryToAggregateTarget, queryToTarget } from '../core/query';
import { AggregateSpec } from '../lite-api/aggregate_types';
import { Query } from '../lite-api/reference';
import { cast } from '../util/input_validation';
import { mapToArray } from '../util/obj';

import { toQueryTarget, toRunAggregationQueryRequest } from './serializer';

/**
* @internal
* @private
*
* This function is for internal use only.
*
* Returns the `QueryTarget` representation of the given query. Returns `null`
* if the Firestore client associated with the given query has not been
* initialized or has been terminated.
*
* @param query - The Query to convert to proto representation.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function _internalQueryToProtoQueryTarget(query: Query): any {
const firestore = cast(query.firestore, Firestore);
const client = ensureFirestoreConfigured(firestore);
const serializer = client._onlineComponents?.datastore.serializer;
if (serializer === undefined) {
return null;
}
return toQueryTarget(serializer!, queryToTarget(query._query)).queryTarget;
}

/**
* @internal
* @private
*
* This function is for internal use only.
*
* Returns `RunAggregationQueryRequest` which contains the proto representation
* of the given aggregation query request. Returns null if the Firestore client
* associated with the given query has not been initialized or has been
* terminated.
*
* @param query - The Query to convert to proto representation.
* @param aggregateSpec - The set of aggregations and their aliases.
*/
export function _internalAggregationQueryToProtoRunAggregationQueryRequest<
AggregateSpecType extends AggregateSpec
// eslint-disable-next-line @typescript-eslint/no-explicit-any
>(query: Query, aggregateSpec: AggregateSpecType): any {
const aggregates = mapToArray(aggregateSpec, (aggregate, alias) => {
return new AggregateImpl(
alias,
aggregate.aggregateType,
aggregate._internalFieldPath
);
});
const firestore = cast(query.firestore, Firestore);
const client = ensureFirestoreConfigured(firestore);
const serializer = client._onlineComponents?.datastore.serializer;
if (serializer === undefined) {
return null;
}

return toRunAggregationQueryRequest(
serializer!,
queryToAggregateTarget(query._query),
aggregates,
/* skipAliasing= */ true
).request;
}
7 changes: 5 additions & 2 deletions packages/firestore/src/remote/serializer.ts
Expand Up @@ -903,7 +903,8 @@ export function toQueryTarget(
export function toRunAggregationQueryRequest(
serializer: JsonProtoSerializer,
target: Target,
aggregates: Aggregate[]
aggregates: Aggregate[],
skipAliasing?: boolean
): {
request: ProtoRunAggregationQueryRequest;
aliasMap: Record<string, string>;
Expand All @@ -919,7 +920,9 @@ export function toRunAggregationQueryRequest(
// Map all client-side aliases to a unique short-form
// alias. This avoids issues with client-side aliases that
// exceed the 1500-byte string size limit.
const serverAlias = `aggregate_${aggregationNum++}`;
const serverAlias = skipAliasing
? aggregate.alias
: `aggregate_${aggregationNum++}`;
aliasMap[serverAlias] = aggregate.alias;

if (aggregate.aggregateType === 'count') {
Expand Down

0 comments on commit f25b9e5

Please sign in to comment.