Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion common/api-review/firestore-lite-pipelines.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export function collectionId(expression: Expression): FunctionExpression;

// @beta
export type CollectionStageOptions = StageOptions & {
collection: string | Query;
collection?: string | Query;
forceIndex?: string;
};

Expand Down Expand Up @@ -943,6 +943,7 @@ export class Pipeline {
addFields(options: AddFieldsStageOptions): Pipeline;
aggregate(accumulator: AliasedAggregate, ...additionalAccumulators: AliasedAggregate[]): Pipeline;
aggregate(options: AggregateStageOptions): Pipeline;
delete(): Pipeline;
distinct(group: string | Selectable, ...additionalGroups: Array<string | Selectable>): Pipeline;
distinct(options: DistinctStageOptions): Pipeline;
findNearest(options: FindNearestStageOptions): Pipeline;
Expand All @@ -968,6 +969,7 @@ export class Pipeline {
union(options: UnionStageOptions): Pipeline;
unnest(selectable: Selectable, indexField?: string): Pipeline;
unnest(options: UnnestStageOptions): Pipeline;
update(...transformedFields: Selectable[]): Pipeline;
where(condition: BooleanExpression): Pipeline;
where(options: WhereStageOptions): Pipeline;
}
Expand Down
6 changes: 5 additions & 1 deletion common/api-review/firestore-pipelines.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export function collectionId(expression: Expression): FunctionExpression;

// @beta
export type CollectionStageOptions = StageOptions & {
collection: string | Query;
collection?: string | Query;
forceIndex?: string;
};

Expand Down Expand Up @@ -946,6 +946,8 @@ export class Pipeline {
// (undocumented)
aggregate(options: AggregateStageOptions): Pipeline;
// (undocumented)
delete(): Pipeline;
// (undocumented)
distinct(group: string | Selectable, ...additionalGroups: Array<string | Selectable>): Pipeline;
// (undocumented)
distinct(options: DistinctStageOptions): Pipeline;
Expand Down Expand Up @@ -992,6 +994,8 @@ export class Pipeline {
// (undocumented)
unnest(options: UnnestStageOptions): Pipeline;
// (undocumented)
update(...transformedFields: Selectable[]): Pipeline;
// (undocumented)
where(condition: BooleanExpression): Pipeline;
// (undocumented)
where(options: WhereStageOptions): Pipeline;
Expand Down
2 changes: 1 addition & 1 deletion packages/firestore/scripts/run-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const argv = yargs
grep: {
type: 'string',
description: 'Filter tests by name (regex)'
},
}
})
.parseSync();

Expand Down
4 changes: 1 addition & 3 deletions packages/firestore/src/lite-api/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ import {
EmulatorMockTokenOptions,
getDefaultEmulatorHostnameAndPort,
isCloudWorkstation,
pingServer,
updateEmulatorBanner
pingServer
} from '@firebase/util';

import {
Expand Down Expand Up @@ -337,7 +336,6 @@ export function connectFirestoreEmulator(
const newHostSetting = `${host}:${port}`;
if (useSsl) {
void pingServer(`https://${newHostSetting}`);
updateEmulatorBanner('Firestore', true);
}
if (settings.host !== DEFAULT_HOST && settings.host !== newHostSetting) {
logWarn(
Expand Down
2 changes: 1 addition & 1 deletion packages/firestore/src/lite-api/pipeline-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export class PipelineSource<PipelineType> {
// Convert user land convenience types to internal types
const normalizedCollection = isString(collectionRefOrString)
? (collectionRefOrString as string)
: collectionRefOrString.path;
: collectionRefOrString!.path;
Comment thread
wu-hui marked this conversation as resolved.
Outdated

// Create stage object
const stage = new CollectionSource(normalizedCollection, options);
Expand Down
51 changes: 51 additions & 0 deletions packages/firestore/src/lite-api/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ import {
Sort,
Stage,
Union,
Delete,
Update,
Unnest,
Where
} from './stage';
Expand All @@ -87,6 +89,7 @@ import {
} from './stage_options';
import { UserDataReader, UserDataSource } from './user_data_reader';
import { AbstractUserDataWriter } from './user_data_writer';
import { CollectionReference } from './reference';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The import of CollectionReference is unused in this file and should be removed to keep the code clean.


/**
* @beta
Expand Down Expand Up @@ -1500,6 +1503,54 @@ export class Pipeline implements ProtoSerializable<ProtoPipeline> {
): Pipeline {
return new Pipeline(db, userDataReader, userDataWriter, stages);
}
/**
* @beta
* Deletes the documents resulting from the pipeline.
*
* @example
* ```typescript
* firestore.pipeline().collection('books').where(field('rating').lt(2)).delete();
* ```
*
* @returns A new Pipeline object with this stage appended to the stage list.
*/
delete(): Pipeline {
const stage = new Delete();

// User data must be read in the context of the API method to
// provide contextual errors
const parseContext = this.userDataReader.createContext(
UserDataSource.Argument,
'delete'
);
stage._readUserData(parseContext);

return this._addStage(stage);
}

/**
* @beta
* Updates the documents resulting from the pipeline.
*
* @example
* ```typescript
* firestore.pipeline().collection('books').update(field('rating').as('bookRating'));
* ```
*
* @param transformedFields - Expressions to apply during the update.
* @returns A new Pipeline object with this stage appended to the stage list.
*/
update(...transformedFields: Selectable[]): Pipeline {
Comment thread
wu-hui marked this conversation as resolved.
const stage = new Update(transformedFields);

const parseContext = this.userDataReader.createContext(
UserDataSource.Argument,
'update'
);
stage._readUserData(parseContext);

return this._addStage(stage);
}
}

export function isPipeline(val: unknown): val is Pipeline {
Expand Down
82 changes: 81 additions & 1 deletion packages/firestore/src/lite-api/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ import {
Expression,
Field,
field,
Ordering
Ordering,
Selectable
} from './expressions';
import { Pipeline } from './pipeline';
import { StageOptions } from './stage_options';
import { isUserData, UserData } from './user_data_reader';
import { selectablesToMap } from '../util/pipeline_util';

/**
* @beta
Expand Down Expand Up @@ -762,3 +764,81 @@ function readUserDataHelper<
}
return expressionMap;
}

/**
* @beta
*/
export class Delete extends Stage {
get _name(): string {
return 'delete';
}

get _optionsUtil(): OptionsUtil {
return new OptionsUtil({});
}

constructor() {
super({});
}

/**
* @internal
* @private
*/
_toProto(serializer: JsonProtoSerializer): ProtoStage {
return {
...super._toProto(serializer),
args: []
};
}

_readUserData(context: ParseContext): void {
super._readUserData(context);
}
}
/**
* @beta
*/
export class Update extends Stage {
get _name(): string {
return 'update';
}

get _optionsUtil(): OptionsUtil {
return new OptionsUtil({});
}

constructor(private transformedFields?: Selectable[]) {
super({});
}

/**
* @internal
* @private
*/
_toProto(serializer: JsonProtoSerializer): ProtoStage {
const args: any[] = [];

if (this.transformedFields && this.transformedFields.length > 0) {
const mapped = selectablesToMap(this.transformedFields);
args.push(toMapValue(serializer, mapped));
} else {
args.push(toMapValue(serializer, new Map()));
}

return {
...super._toProto(serializer),
args
};
}

_readUserData(context: ParseContext): void {
super._readUserData(context);
if (this.transformedFields) {
readUserDataHelper(
this.transformedFields as unknown as UserData[],
context
);
}
}
}
2 changes: 1 addition & 1 deletion packages/firestore/src/lite-api/stage_options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export type CollectionStageOptions = StageOptions & {
* @beta
* Name or reference to the collection that will be used as the Pipeline source.
*/
collection: string | CollectionReference;
collection?: string | CollectionReference;

/**
* @beta
Expand Down
4 changes: 2 additions & 2 deletions packages/firestore/src/lite-api/user_data_writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
import { isValidResourceName } from '../remote/serializer';
import { fail, hardAssert } from '../util/assert';
import { ByteString } from '../util/byte_string';
import { logError } from '../util/log';
import { logDebug } from '../util/log';
import { forEach } from '../util/obj';

import { GeoPoint } from './geo_point';
Expand Down Expand Up @@ -184,7 +184,7 @@ export abstract class AbstractUserDataWriter {

if (!databaseId.isEqual(expectedDatabaseId)) {
// TODO(b/64130202): Somehow support foreign references.
logError(
logDebug(
`Document ${key} contains a document ` +
`reference within a different database (` +
`${databaseId.projectId}/${databaseId.database}) which is not ` +
Expand Down
6 changes: 5 additions & 1 deletion packages/firestore/src/remote/rpc_error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,11 @@ export function isPermanentError(code: Code): boolean {
case Code.DATA_LOSS:
return true;
default:
return fail(0x3c6b, 'Unknown status code', { code });
// If we encounter an unknown error code, we treat it as a permanent error.
// This can happen if a non-Firestore error (like an Auth or Storage error)
// is passed into this function.
logError(`isPermanentError: Unknown status code: ${code}`);
return true;
}
}

Expand Down
17 changes: 10 additions & 7 deletions packages/firestore/src/remote/watch_change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,16 @@ class TargetState {
}

recordTargetResponse(): void {
this.pendingResponses -= 1;
hardAssert(
this.pendingResponses >= 0,
0x0ca9,
'`pendingResponses` is less than 0. This indicates that the SDK received more target acks from the server than expected. The SDK should not continue to operate.',
{ pendingResponses: this.pendingResponses }
);
if (this.pendingResponses > 0) {
this.pendingResponses -= 1;
} else {
// This can happen if the server sends more target acks than expected.
// We log this but continue to operate to avoid crashing the app.
logWarn(
'recordTargetResponse: pendingResponses is already 0. ' +
'This indicates that the SDK received more target acks from the server than expected.'
);
}
}

markCurrent(): void {
Expand Down
Loading
Loading