@firebase/firestore
Version:
The Cloud Firestore component of the Firebase JS SDK.
1,379 lines (1,373 loc) • 161 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var common6d85b8e5_node = require('./common-29bfb23b.node.cjs.js');
require('@firebase/util');
require('crypto');
require('@firebase/logger');
require('util');
require('@firebase/webchannel-wrapper/bloom-blob');
require('@firebase/app');
/**
* @license
* Copyright 2025 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.
*/
class OptionsUtil {
constructor(optionDefinitions) {
this.optionDefinitions = optionDefinitions;
}
_getKnownOptions(options, context) {
const knownOptions = common6d85b8e5_node.ObjectValue.empty();
// SERIALIZE KNOWN OPTIONS
for (const knownOptionKey in this.optionDefinitions) {
if (this.optionDefinitions.hasOwnProperty(knownOptionKey)) {
const optionDefinition = this.optionDefinitions[knownOptionKey];
if (knownOptionKey in options) {
const optionValue = options[knownOptionKey];
let protoValue = undefined;
if (optionDefinition.nestedOptions && common6d85b8e5_node.isPlainObject(optionValue)) {
const nestedUtil = new OptionsUtil(optionDefinition.nestedOptions);
protoValue = {
mapValue: {
fields: nestedUtil.getOptionsProto(context, optionValue)
}
};
}
else if (optionValue) {
protoValue = common6d85b8e5_node.parseData(optionValue, context) ?? undefined;
}
if (protoValue) {
knownOptions.set(common6d85b8e5_node.FieldPath$1.fromServerFormat(optionDefinition.serverName), protoValue);
}
}
}
}
return knownOptions;
}
getOptionsProto(context, knownOptions, optionsOverride) {
const result = this._getKnownOptions(knownOptions, context);
// APPLY OPTIONS OVERRIDES
if (optionsOverride) {
const optionsMap = new Map(common6d85b8e5_node.mapToArray(optionsOverride, (value, key) => [
common6d85b8e5_node.FieldPath$1.fromServerFormat(key),
value !== undefined ? common6d85b8e5_node.parseData(value, context) : null
]));
result.setAll(optionsMap);
}
// Return MapValue from `result` or empty map value
return result.value.mapValue.fields ?? {};
}
}
/**
* @license
* Copyright 2025 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.
*/
class StructuredPipelineOptions {
constructor(_userOptions = {}, _optionsOverride = {}) {
this._userOptions = _userOptions;
this._optionsOverride = _optionsOverride;
this.optionsUtil = new OptionsUtil({
indexMode: {
serverName: 'index_mode'
}
});
}
_readUserData(context) {
this.proto = this.optionsUtil.getOptionsProto(context, this._userOptions, this._optionsOverride);
}
}
class StructuredPipeline {
constructor(pipeline, options) {
this.pipeline = pipeline;
this.options = options;
}
_toProto(serializer) {
return {
pipeline: this.pipeline._toProto(serializer),
options: this.options.proto
};
}
}
/**
* @license
* Copyright 2024 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.
*/
/* eslint @typescript-eslint/no-explicit-any: 0 */
function isITimestamp(obj) {
if (typeof obj !== 'object' || obj === null) {
return false; // Must be a non-null object
}
if ('seconds' in obj &&
(obj.seconds === null ||
typeof obj.seconds === 'number' ||
typeof obj.seconds === 'string') &&
'nanos' in obj &&
(obj.nanos === null || typeof obj.nanos === 'number')) {
return true;
}
return false;
}
function isILatLng(obj) {
if (typeof obj !== 'object' || obj === null) {
return false; // Must be a non-null object
}
if ('latitude' in obj &&
(obj.latitude === null || typeof obj.latitude === 'number') &&
'longitude' in obj &&
(obj.longitude === null || typeof obj.longitude === 'number')) {
return true;
}
return false;
}
function isIArrayValue(obj) {
if (typeof obj !== 'object' || obj === null) {
return false; // Must be a non-null object
}
if ('values' in obj && (obj.values === null || Array.isArray(obj.values))) {
return true;
}
return false;
}
function isIMapValue(obj) {
if (typeof obj !== 'object' || obj === null) {
return false; // Must be a non-null object
}
if ('fields' in obj && (obj.fields === null || common6d85b8e5_node.isPlainObject(obj.fields))) {
return true;
}
return false;
}
function isIFunction(obj) {
if (typeof obj !== 'object' || obj === null) {
return false; // Must be a non-null object
}
if ('name' in obj &&
(obj.name === null || typeof obj.name === 'string') &&
'args' in obj &&
(obj.args === null || Array.isArray(obj.args))) {
return true;
}
return false;
}
function isIPipeline(obj) {
if (typeof obj !== 'object' || obj === null) {
return false; // Must be a non-null object
}
if ('stages' in obj && (obj.stages === null || Array.isArray(obj.stages))) {
return true;
}
return false;
}
function isFirestoreValue(obj) {
if (typeof obj !== 'object' || obj === null) {
return false; // Must be a non-null object
}
// Check optional properties and their types
if (('nullValue' in obj &&
(obj.nullValue === null || obj.nullValue === 'NULL_VALUE')) ||
('booleanValue' in obj &&
(obj.booleanValue === null || typeof obj.booleanValue === 'boolean')) ||
('integerValue' in obj &&
(obj.integerValue === null ||
typeof obj.integerValue === 'number' ||
typeof obj.integerValue === 'string')) ||
('doubleValue' in obj &&
(obj.doubleValue === null || typeof obj.doubleValue === 'number')) ||
('timestampValue' in obj &&
(obj.timestampValue === null || isITimestamp(obj.timestampValue))) ||
('stringValue' in obj &&
(obj.stringValue === null || typeof obj.stringValue === 'string')) ||
('bytesValue' in obj &&
(obj.bytesValue === null || obj.bytesValue instanceof Uint8Array)) ||
('referenceValue' in obj &&
(obj.referenceValue === null ||
typeof obj.referenceValue === 'string')) ||
('geoPointValue' in obj &&
(obj.geoPointValue === null || isILatLng(obj.geoPointValue))) ||
('arrayValue' in obj &&
(obj.arrayValue === null || isIArrayValue(obj.arrayValue))) ||
('mapValue' in obj &&
(obj.mapValue === null || isIMapValue(obj.mapValue))) ||
('fieldReferenceValue' in obj &&
(obj.fieldReferenceValue === null ||
typeof obj.fieldReferenceValue === 'string')) ||
('functionValue' in obj &&
(obj.functionValue === null || isIFunction(obj.functionValue))) ||
('pipelineValue' in obj &&
(obj.pipelineValue === null || isIPipeline(obj.pipelineValue)))) {
return true;
}
return false;
}
/**
* @license
* Copyright 2024 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.
*/
/**
* Converts a value to an Expression, Returning either a Constant, MapFunction,
* ArrayFunction, or the input itself (if it's already an expression).
*
* @private
* @internal
* @param value
*/
function valueToDefaultExpr$1(value) {
let result;
if (value instanceof Expression) {
return value;
}
else if (common6d85b8e5_node.isPlainObject(value)) {
result = _map(value);
}
else if (value instanceof Array) {
result = array(value);
}
else {
result = _constant(value, undefined);
}
return result;
}
/**
* Converts a value to an Expression, Returning either a Constant, MapFunction,
* ArrayFunction, or the input itself (if it's already an expression).
*
* @private
* @internal
* @param value
*/
function vectorToExpr$1(value) {
if (value instanceof Expression) {
return value;
}
else if (value instanceof common6d85b8e5_node.VectorValue) {
return constant(value);
}
else if (Array.isArray(value)) {
return constant(common6d85b8e5_node.vector(value));
}
else {
throw new Error('Unsupported value: ' + typeof value);
}
}
/**
* Converts a value to an Expression, Returning either a Constant, MapFunction,
* ArrayFunction, or the input itself (if it's already an expression).
* If the input is a string, it is assumed to be a field name, and a
* field(value) is returned.
*
* @private
* @internal
* @param value
*/
function fieldOrExpression$1(value) {
if (common6d85b8e5_node.isString(value)) {
const result = field(value);
return result;
}
else {
return valueToDefaultExpr$1(value);
}
}
/**
* @beta
*
* Represents an expression that can be evaluated to a value within the execution of a {@link
* @firebase/firestore/pipelines#Pipeline}.
*
* Expressions are the building blocks for creating complex queries and transformations in
* Firestore pipelines. They can represent:
*
* - **Field references:** Access values from document fields.
* - **Literals:** Represent constant values (strings, numbers, booleans).
* - **Function calls:** Apply functions to one or more expressions.
*
* The `Expression` class provides a fluent API for building expressions. You can chain together
* method calls to create complex expressions.
*/
class Expression {
constructor() {
this._protoValueType = 'ProtoValue';
}
/**
* Creates an expression that adds this expression to another expression.
*
* @example
* ```typescript
* // Add the value of the 'quantity' field and the 'reserve' field.
* field("quantity").add(field("reserve"));
* ```
*
* @param second - The expression or literal to add to this expression.
* @param others - Optional additional expressions or literals to add to this expression.
* @returns A new `Expression` representing the addition operation.
*/
add(second) {
return new FunctionExpression('add', [this, valueToDefaultExpr$1(second)], 'add');
}
/**
* @beta
* Wraps the expression in a [BooleanExpression].
*
* @returns A [BooleanExpression] representing the same expression.
*/
asBoolean() {
if (this instanceof BooleanExpression) {
return this;
}
else if (this instanceof Constant) {
return new BooleanConstant(this);
}
else if (this instanceof Field) {
return new BooleanField(this);
}
else if (this instanceof FunctionExpression) {
return new BooleanFunctionExpression(this);
}
else {
throw new common6d85b8e5_node.FirestoreError('invalid-argument', `Conversion of type ${typeof this} to BooleanExpression not supported.`);
}
}
subtract(subtrahend) {
return new FunctionExpression('subtract', [this, valueToDefaultExpr$1(subtrahend)], 'subtract');
}
/**
* @beta
* Creates an expression that multiplies this expression by another expression.
*
* @example
* ```typescript
* // Multiply the 'quantity' field by the 'price' field
* field("quantity").multiply(field("price"));
* ```
*
* @param second - The second expression or literal to multiply by.
* @param others - Optional additional expressions or literals to multiply by.
* @returns A new `Expression` representing the multiplication operation.
*/
multiply(second) {
return new FunctionExpression('multiply', [this, valueToDefaultExpr$1(second)], 'multiply');
}
divide(divisor) {
return new FunctionExpression('divide', [this, valueToDefaultExpr$1(divisor)], 'divide');
}
mod(other) {
return new FunctionExpression('mod', [this, valueToDefaultExpr$1(other)], 'mod');
}
equal(other) {
return new FunctionExpression('equal', [this, valueToDefaultExpr$1(other)], 'equal').asBoolean();
}
notEqual(other) {
return new FunctionExpression('not_equal', [this, valueToDefaultExpr$1(other)], 'notEqual').asBoolean();
}
lessThan(other) {
return new FunctionExpression('less_than', [this, valueToDefaultExpr$1(other)], 'lessThan').asBoolean();
}
lessThanOrEqual(other) {
return new FunctionExpression('less_than_or_equal', [this, valueToDefaultExpr$1(other)], 'lessThanOrEqual').asBoolean();
}
greaterThan(other) {
return new FunctionExpression('greater_than', [this, valueToDefaultExpr$1(other)], 'greaterThan').asBoolean();
}
greaterThanOrEqual(other) {
return new FunctionExpression('greater_than_or_equal', [this, valueToDefaultExpr$1(other)], 'greaterThanOrEqual').asBoolean();
}
/**
* @beta
* Creates an expression that concatenates an array expression with one or more other arrays.
*
* @example
* ```typescript
* // Combine the 'items' array with another array field.
* field("items").arrayConcat(field("otherItems"));
* ```
* @param secondArray - Second array expression or array literal to concatenate.
* @param otherArrays - Optional additional array expressions or array literals to concatenate.
* @returns A new `Expression` representing the concatenated array.
*/
arrayConcat(secondArray, ...otherArrays) {
const elements = [secondArray, ...otherArrays];
const exprValues = elements.map(value => valueToDefaultExpr$1(value));
return new FunctionExpression('array_concat', [this, ...exprValues], 'arrayConcat');
}
arrayContains(element) {
return new FunctionExpression('array_contains', [this, valueToDefaultExpr$1(element)], 'arrayContains').asBoolean();
}
arrayContainsAll(values) {
const normalizedExpr = Array.isArray(values)
? new ListOfExprs(values.map(valueToDefaultExpr$1), 'arrayContainsAll')
: values;
return new FunctionExpression('array_contains_all', [this, normalizedExpr], 'arrayContainsAll').asBoolean();
}
arrayContainsAny(values) {
const normalizedExpr = Array.isArray(values)
? new ListOfExprs(values.map(valueToDefaultExpr$1), 'arrayContainsAny')
: values;
return new FunctionExpression('array_contains_any', [this, normalizedExpr], 'arrayContainsAny').asBoolean();
}
/**
* @beta
* Creates an expression that reverses an array.
*
* @example
* ```typescript
* // Reverse the value of the 'myArray' field.
* field("myArray").arrayReverse();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed array.
*/
arrayReverse() {
return new FunctionExpression('array_reverse', [this]);
}
/**
* @beta
* Creates an expression that calculates the length of an array.
*
* @example
* ```typescript
* // Get the number of items in the 'cart' array
* field("cart").arrayLength();
* ```
*
* @returns A new `Expression` representing the length of the array.
*/
arrayLength() {
return new FunctionExpression('array_length', [this], 'arrayLength');
}
equalAny(others) {
const exprOthers = Array.isArray(others)
? new ListOfExprs(others.map(valueToDefaultExpr$1), 'equalAny')
: others;
return new FunctionExpression('equal_any', [this, exprOthers], 'equalAny').asBoolean();
}
notEqualAny(others) {
const exprOthers = Array.isArray(others)
? new ListOfExprs(others.map(valueToDefaultExpr$1), 'notEqualAny')
: others;
return new FunctionExpression('not_equal_any', [this, exprOthers], 'notEqualAny').asBoolean();
}
/**
* @beta
* Creates an expression that checks if a field exists in the document.
*
* @example
* ```typescript
* // Check if the document has a field named "phoneNumber"
* field("phoneNumber").exists();
* ```
*
* @returns A new `Expression` representing the 'exists' check.
*/
exists() {
return new FunctionExpression('exists', [this], 'exists').asBoolean();
}
/**
* @beta
* Creates an expression that calculates the character length of a string in UTF-8.
*
* @example
* ```typescript
* // Get the character length of the 'name' field in its UTF-8 form.
* field("name").charLength();
* ```
*
* @returns A new `Expression` representing the length of the string.
*/
charLength() {
return new FunctionExpression('char_length', [this], 'charLength');
}
like(stringOrExpr) {
return new FunctionExpression('like', [this, valueToDefaultExpr$1(stringOrExpr)], 'like').asBoolean();
}
regexContains(stringOrExpr) {
return new FunctionExpression('regex_contains', [this, valueToDefaultExpr$1(stringOrExpr)], 'regexContains').asBoolean();
}
regexFind(stringOrExpr) {
return new FunctionExpression('regex_find', [this, valueToDefaultExpr$1(stringOrExpr)], 'regexFind');
}
regexFindAll(stringOrExpr) {
return new FunctionExpression('regex_find_all', [this, valueToDefaultExpr$1(stringOrExpr)], 'regexFindAll');
}
regexMatch(stringOrExpr) {
return new FunctionExpression('regex_match', [this, valueToDefaultExpr$1(stringOrExpr)], 'regexMatch').asBoolean();
}
stringContains(stringOrExpr) {
return new FunctionExpression('string_contains', [this, valueToDefaultExpr$1(stringOrExpr)], 'stringContains').asBoolean();
}
startsWith(stringOrExpr) {
return new FunctionExpression('starts_with', [this, valueToDefaultExpr$1(stringOrExpr)], 'startsWith').asBoolean();
}
endsWith(stringOrExpr) {
return new FunctionExpression('ends_with', [this, valueToDefaultExpr$1(stringOrExpr)], 'endsWith').asBoolean();
}
/**
* @beta
* Creates an expression that converts a string to lowercase.
*
* @example
* ```typescript
* // Convert the 'name' field to lowercase
* field("name").toLower();
* ```
*
* @returns A new `Expression` representing the lowercase string.
*/
toLower() {
return new FunctionExpression('to_lower', [this], 'toLower');
}
/**
* @beta
* Creates an expression that converts a string to uppercase.
*
* @example
* ```typescript
* // Convert the 'title' field to uppercase
* field("title").toUpper();
* ```
*
* @returns A new `Expression` representing the uppercase string.
*/
toUpper() {
return new FunctionExpression('to_upper', [this], 'toUpper');
}
/**
* @beta
* Creates an expression that removes leading and trailing characters from a string or byte array.
*
* @example
* ```typescript
* // Trim whitespace from the 'userInput' field
* field("userInput").trim();
*
* // Trim quotes from the 'userInput' field
* field("userInput").trim('"');
* ```
* @param valueToTrim - Optional This parameter is treated as a set of characters or bytes that will be
* trimmed from the input. If not specified, then whitespace will be trimmed.
* @returns A new `Expression` representing the trimmed string or byte array.
*/
trim(valueToTrim) {
const args = [this];
if (valueToTrim) {
args.push(valueToDefaultExpr$1(valueToTrim));
}
return new FunctionExpression('trim', args, 'trim');
}
/**
* @beta
* Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array.
*
* @example
* ```typescript
* // Trim whitespace from the beginning of the 'userInput' field
* field("userInput").ltrim();
*
* // Trim quotes from the beginning of the 'userInput' field
* field("userInput").ltrim('"');
* ```
*
* @param valueToTrim - Optional. A string or byte array containing the characters/bytes to trim.
* If not specified, whitespace will be trimmed.
* @returns A new `Expression` representing the trimmed string.
*/
ltrim(valueToTrim) {
const args = [this];
if (valueToTrim) {
args.push(valueToDefaultExpr$1(valueToTrim));
}
return new FunctionExpression('ltrim', args, 'ltrim');
}
/**
* @beta
* Trims whitespace or a specified set of characters/bytes from the end of a string or byte array.
*
* @example
* ```typescript
* // Trim whitespace from the end of the 'userInput' field
* field("userInput").rtrim();
*
* // Trim quotes from the end of the 'userInput' field
* field("userInput").rtrim('"');
* ```
*
* @param valueToTrim - Optional. A string or byte array containing the characters/bytes to trim.
* If not specified, whitespace will be trimmed.
* @returns A new `Expression` representing the trimmed string or byte array.
*/
rtrim(valueToTrim) {
const args = [this];
if (valueToTrim) {
args.push(valueToDefaultExpr$1(valueToTrim));
}
return new FunctionExpression('rtrim', args, 'rtrim');
}
/**
* @beta
* Creates an expression that returns the data type of this expression's result, as a string.
*
* @remarks
* This is evaluated on the backend. This means:
* 1. Generic typed elements (like `array<string>`) evaluate strictly to the primitive `'array'`.
* 2. Any custom `FirestoreDataConverter` mappings are ignored.
* 3. For numeric values, the backend does not yield the JavaScript `"number"` type; it evaluates
* precisely as `"int64"` or `"float64"`.
* 4. For date or timestamp objects, the backend evaluates to `"timestamp"`.
*
* @example
* ```typescript
* // Get the data type of the value in field 'title'
* field('title').type()
* ```
*
* @returns A new `Expression` representing the data type.
*/
type() {
return new FunctionExpression('type', [this]);
}
/**
* @beta
* Creates an expression that checks if the result of this expression is of the given type.
*
* @remarks Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data.
*
* @example
* ```typescript
* // Check if the 'price' field is specifically an integer (not just 'number')
* field('price').isType('int64');
* ```
*
* @param type - The type to check for.
* @returns A new `BooleanExpression` that evaluates to true if the expression's result is of the given type, false otherwise.
*/
isType(type) {
return new FunctionExpression('is_type', [this, constant(type)], 'isType').asBoolean();
}
/**
* @beta
* Creates an expression that concatenates string expressions together.
*
* @example
* ```typescript
* // Combine the 'firstName', " ", and 'lastName' fields into a single string
* field("firstName").stringConcat(constant(" "), field("lastName"));
* ```
*
* @param secondString - The additional expression or string literal to concatenate.
* @param otherStrings - Optional additional expressions or string literals to concatenate.
* @returns A new `Expression` representing the concatenated string.
*/
stringConcat(secondString, ...otherStrings) {
const elements = [secondString, ...otherStrings];
const exprs = elements.map(valueToDefaultExpr$1);
return new FunctionExpression('string_concat', [this, ...exprs], 'stringConcat');
}
/**
* @beta
* Creates an expression that finds the index of the first occurrence of a substring or byte sequence.
*
* @example
* ```typescript
* // Find the index of "foo" in the 'text' field
* field("text").stringIndexOf("foo");
* ```
*
* @param search - The substring or byte sequence to search for.
* @returns A new `Expression` representing the index of the first occurrence.
*/
stringIndexOf(search) {
return new FunctionExpression('string_index_of', [this, valueToDefaultExpr$1(search)], 'stringIndexOf');
}
/**
* @beta
* Creates an expression that repeats a string or byte array a specified number of times.
*
* @example
* ```typescript
* // Repeat the 'label' field 3 times
* field("label").stringRepeat(3);
* ```
*
* @param repetitions - The number of times to repeat the string or byte array.
* @returns A new `Expression` representing the repeated string or byte array.
*/
stringRepeat(repetitions) {
return new FunctionExpression('string_repeat', [this, valueToDefaultExpr$1(repetitions)], 'stringRepeat');
}
/**
* @beta
* Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement.
*
* @example
* ```typescript
* // Replace all occurrences of "foo" with "bar" in the 'text' field
* field("text").stringReplaceAll("foo", "bar");
* ```
*
* @param find - The substring or byte sequence to search for.
* @param replacement - The replacement string or byte sequence.
* @returns A new `Expression` representing the string or byte array with replacements.
*/
stringReplaceAll(find, replacement) {
return new FunctionExpression('string_replace_all', [this, valueToDefaultExpr$1(find), valueToDefaultExpr$1(replacement)], 'stringReplaceAll');
}
/**
* @beta
* Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement.
*
* @example
* ```typescript
* // Replace the first occurrence of "foo" with "bar" in the 'text' field
* field("text").stringReplaceOne("foo", "bar");
* ```
*
* @param find - The substring or byte sequence to search for.
* @param replacement - The replacement string or byte sequence.
* @returns A new `Expression` representing the string or byte array with the replacement.
*/
stringReplaceOne(find, replacement) {
return new FunctionExpression('string_replace_one', [this, valueToDefaultExpr$1(find), valueToDefaultExpr$1(replacement)], 'stringReplaceOne');
}
/**
* @beta
* Creates an expression that concatenates expression results together.
*
* @example
* ```typescript
* // Combine the 'firstName', ' ', and 'lastName' fields into a single value.
* field("firstName").concat(constant(" "), field("lastName"));
* ```
*
* @param second - The additional expression or literal to concatenate.
* @param others - Optional additional expressions or literals to concatenate.
* @returns A new `Expression` representing the concatenated value.
*/
concat(second, ...others) {
const elements = [second, ...others];
const exprs = elements.map(valueToDefaultExpr$1);
return new FunctionExpression('concat', [this, ...exprs], 'concat');
}
/**
* @beta
* Creates an expression that reverses this string expression.
*
* @example
* ```typescript
* // Reverse the value of the 'myString' field.
* field("myString").reverse();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed string.
*/
reverse() {
return new FunctionExpression('reverse', [this], 'reverse');
}
/**
* @beta
* Returns the first element of the array.
*
* @example
* ```typescript
* // Get the first element of the 'myArray' field.
* field("myArray").arrayFirst();
* ```
*
* @returns A new `Expression` representing the first element.
*/
arrayFirst() {
return new FunctionExpression('array_first', [this], 'arrayFirst');
}
arrayFirstN(n) {
return new FunctionExpression('array_first_n', [this, valueToDefaultExpr$1(n)], 'arrayFirstN');
}
/**
* @beta
* Returns the last element of the array.
*
* @example
* ```typescript
* // Get the last element of the 'myArray' field.
* field("myArray").arrayLast();
* ```
*
* @returns A new `Expression` representing the last element.
*/
arrayLast() {
return new FunctionExpression('array_last', [this], 'arrayLast');
}
arrayLastN(n) {
return new FunctionExpression('array_last_n', [this, valueToDefaultExpr$1(n)], 'arrayLastN');
}
/**
* @beta
* Returns the maximum value in the array.
*
* @example
* ```typescript
* // Get the maximum value of the 'myArray' field.
* field("myArray").arrayMaximum();
* ```
*
* @returns A new `Expression` representing the maximum value.
*/
arrayMaximum() {
return new FunctionExpression('maximum', [this], 'arrayMaximum');
}
arrayMaximumN(n) {
return new FunctionExpression('maximum_n', [this, valueToDefaultExpr$1(n)], 'arrayMaximumN');
}
/**
* @beta
* Returns the minimum value in the array.
*
* @example
* ```typescript
* // Get the minimum value of the 'myArray' field.
* field("myArray").arrayMinimum();
* ```
*
* @returns A new `Expression` representing the minimum value.
*/
arrayMinimum() {
return new FunctionExpression('minimum', [this], 'arrayMinimum');
}
arrayMinimumN(n) {
return new FunctionExpression('minimum_n', [this, valueToDefaultExpr$1(n)], 'arrayMinimumN');
}
arrayIndexOf(search) {
return new FunctionExpression('array_index_of', [this, valueToDefaultExpr$1(search), valueToDefaultExpr$1('first')], 'arrayIndexOf');
}
arrayLastIndexOf(search) {
return new FunctionExpression('array_index_of', [this, valueToDefaultExpr$1(search), valueToDefaultExpr$1('last')], 'arrayLastIndexOf');
}
arrayIndexOfAll(search) {
return new FunctionExpression('array_index_of_all', [this, valueToDefaultExpr$1(search)], 'arrayIndexOfAll');
}
/**
* @beta
* Creates an expression that calculates the length of this string expression in bytes.
*
* @example
* ```typescript
* // Calculate the length of the 'myString' field in bytes.
* field("myString").byteLength();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the string in bytes.
*/
byteLength() {
return new FunctionExpression('byte_length', [this], 'byteLength');
}
/**
* @beta
* Creates an expression that computes the ceiling of a numeric value.
*
* @example
* ```typescript
* // Compute the ceiling of the 'price' field.
* field("price").ceil();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the ceiling of the numeric value.
*/
ceil() {
return new FunctionExpression('ceil', [this]);
}
/**
* @beta
* Creates an expression that computes the floor of a numeric value.
*
* @example
* ```typescript
* // Compute the floor of the 'price' field.
* field("price").floor();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the floor of the numeric value.
*/
floor() {
return new FunctionExpression('floor', [this]);
}
/**
* @beta
* Creates an expression that computes the absolute value of a numeric value.
*
* @example
* ```typescript
* // Compute the absolute value of the 'price' field.
* field("price").abs();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the absolute value of the numeric value.
*/
abs() {
return new FunctionExpression('abs', [this]);
}
/**
* @beta
* Creates an expression that computes e to the power of this expression.
*
* @example
* ```typescript
* // Compute e to the power of the 'value' field.
* field("value").exp();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the exp of the numeric value.
*/
exp() {
return new FunctionExpression('exp', [this]);
}
/**
* @beta
* Accesses a value from a map (object) field using the provided key.
*
* @example
* ```typescript
* // Get the 'city' value from the 'address' map field
* field("address").mapGet("city");
* ```
*
* @param subfield - The key to access in the map.
* @returns A new `Expression` representing the value associated with the given key in the map.
*/
mapGet(subfield) {
return new FunctionExpression('map_get', [this, constant(subfield)], 'mapGet');
}
/**
* @beta
* Creates an expression that returns a new map with the specified entries added or updated.
*
* @remarks
* Note that `mapSet` only performs shallow updates to the map. Setting a value to `null`
* will retain the key with a `null` value. To remove a key entirely, use `mapRemove`.
*
* @example
* ```typescript
* // Set the 'city' to "San Francisco" in the 'address' map
* field("address").mapSet("city", "San Francisco");
* ```
*
* @param key - The key to set. Must be a string or a constant string expression.
* @param value - The value to set.
* @param moreKeyValues - Additional key-value pairs to set.
* @returns A new `Expression` representing the map with the entries set.
*/
mapSet(key, value, ...moreKeyValues) {
const args = [
this,
valueToDefaultExpr$1(key),
valueToDefaultExpr$1(value),
...moreKeyValues.map(valueToDefaultExpr$1)
];
return new FunctionExpression('map_set', args, 'mapSet');
}
/**
* @beta
* Creates an expression that returns the keys of a map.
*
* @remarks
* While the backend generally preserves insertion order, relying on the
* order of the output array is not guaranteed and should be avoided.
*
* @example
* ```typescript
* // Get the keys of the 'address' map
* field("address").mapKeys();
* ```
*
* @returns A new `Expression` representing the keys of the map.
*/
mapKeys() {
return new FunctionExpression('map_keys', [this], 'mapKeys');
}
/**
* @beta
* Creates an expression that returns the values of a map.
*
* @remarks
* While the backend generally preserves insertion order, relying on the
* order of the output array is not guaranteed and should be avoided.
*
* @example
* ```typescript
* // Get the values of the 'address' map
* field("address").mapValues();
* ```
*
* @returns A new `Expression` representing the values of the map.
*/
mapValues() {
return new FunctionExpression('map_values', [this], 'mapValues');
}
/**
* @beta
* Creates an expression that returns the entries of a map as an array of maps,
* where each map contains a `"k"` property for the key and a `"v"` property for the value.
* For example: `[{ k: "key1", v: "value1" }, ...]`.
*
* @example
* ```typescript
* // Get the entries of the 'address' map
* field("address").mapEntries();
* ```
*
* @returns A new `Expression` representing the entries of the map.
*/
mapEntries() {
return new FunctionExpression('map_entries', [this], 'mapEntries');
}
/**
* @beta
* Creates an aggregation that counts the number of stage inputs with valid evaluations of the
* expression or field.
*
* @example
* ```typescript
* // Count the total number of products
* field("productId").count().as("totalProducts");
* ```
*
* @returns A new `AggregateFunction` representing the 'count' aggregation.
*/
count() {
return AggregateFunction._create('count', [this], 'count');
}
/**
* @beta
* Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs.
*
* @example
* ```typescript
* // Calculate the total revenue from a set of orders
* field("orderAmount").sum().as("totalRevenue");
* ```
*
* @returns A new `AggregateFunction` representing the 'sum' aggregation.
*/
sum() {
return AggregateFunction._create('sum', [this], 'sum');
}
/**
* @beta
* Creates an aggregation that calculates the average (mean) of a numeric field across multiple
* stage inputs.
*
* @example
* ```typescript
* // Calculate the average age of users
* field("age").average().as("averageAge");
* ```
*
* @returns A new `AggregateFunction` representing the 'average' aggregation.
*/
average() {
return AggregateFunction._create('average', [this], 'average');
}
/**
* @beta
* Creates an aggregation that finds the minimum value of a field across multiple stage inputs.
*
* @example
* ```typescript
* // Find the lowest price of all products
* field("price").minimum().as("lowestPrice");
* ```
*
* @returns A new `AggregateFunction` representing the 'minimum' aggregation.
*/
minimum() {
return AggregateFunction._create('minimum', [this], 'minimum');
}
/**
* @beta
* Creates an aggregation that finds the maximum value of a field across multiple stage inputs.
*
* @example
* ```typescript
* // Find the highest score in a leaderboard
* field("score").maximum().as("highestScore");
* ```
*
* @returns A new `AggregateFunction` representing the 'maximum' aggregation.
*/
maximum() {
return AggregateFunction._create('maximum', [this], 'maximum');
}
/**
* @beta
* Creates an aggregation that finds the first value of an expression across multiple stage inputs.
*
* @example
* ```typescript
* // Find the first value of the 'rating' field
* field("rating").first().as("firstRating");
* ```
*
* @returns A new `AggregateFunction` representing the 'first' aggregation.
*/
first() {
return AggregateFunction._create('first', [this], 'first');
}
/**
* @beta
* Creates an aggregation that finds the last value of an expression across multiple stage inputs.
*
* @example
* ```typescript
* // Find the last value of the 'rating' field
* field("rating").last().as("lastRating");
* ```
*
* @returns A new `AggregateFunction` representing the 'last' aggregation.
*/
last() {
return AggregateFunction._create('last', [this], 'last');
}
/**
* @beta
* Creates an aggregation that collects all values of an expression across multiple stage inputs
* into an array.
*
* @remarks
* If the expression resolves to an absent value, it is converted to `null`.
* The order of elements in the output array is not stable and shouldn't be relied upon.
*
* @example
* ```typescript
* // Collect all tags from books into an array
* field("tags").arrayAgg().as("allTags");
* ```
*
* @returns A new `AggregateFunction` representing the 'array_agg' aggregation.
*/
arrayAgg() {
return AggregateFunction._create('array_agg', [this], 'arrayAgg');
}
/**
* @beta
* Creates an aggregation that collects all distinct values of an expression across multiple stage
* inputs into an array.
*
* @remarks
* If the expression resolves to an absent value, it is converted to `null`.
* The order of elements in the output array is not stable and shouldn't be relied upon.
*
* @example
* ```typescript
* // Collect all distinct tags from books into an array
* field("tags").arrayAggDistinct().as("allDistinctTags");
* ```
*
* @returns A new `AggregateFunction` representing the 'array_agg_distinct' aggregation.
*/
arrayAggDistinct() {
return AggregateFunction._create('array_agg_distinct', [this], 'arrayAggDistinct');
}
/**
* @beta
* Creates an aggregation that counts the number of distinct values of the expression or field.
*
* @example
* ```typescript
* // Count the distinct number of products
* field("productId").countDistinct().as("distinctProducts");
* ```
*
* @returns A new `AggregateFunction` representing the 'count_distinct' aggregation.
*/
countDistinct() {
return AggregateFunction._create('count_distinct', [this], 'countDistinct');
}
/**
* @beta
* Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering.
*
* @example
* ```typescript
* // Returns the larger value between the 'timestamp' field and the current timestamp.
* field("timestamp").logicalMaximum(currentTimestamp());
* ```
*
* @param second - The second expression or literal to compare with.
* @param others - Optional additional expressions or literals to compare with.
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logical maximum operation.
*/
logicalMaximum(second, ...others) {
const values = [second, ...others];
return new FunctionExpression('maximum', [this, ...values.map(valueToDefaultExpr$1)], 'logicalMaximum');
}
/**
* @beta
* Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering.
*
* @example
* ```typescript
* // Returns the smaller value between the 'timestamp' field and the current timestamp.
* field("timestamp").logicalMinimum(currentTimestamp());
* ```
*
* @param second - The second expression or literal to compare with.
* @param others - Optional additional expressions or literals to compare with.
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the logical minimum operation.
*/
logicalMinimum(second, ...others) {
const values = [second, ...others];
return new FunctionExpression('minimum', [this, ...values.map(valueToDefaultExpr$1)], 'minimum');
}
/**
* @beta
* Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression.
*
* @example
* ```typescript
* // Get the vector length (dimension) of the field 'embedding'.
* field("embedding").vectorLength();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the length of the vector.
*/
vectorLength() {
return new FunctionExpression('vector_length', [this], 'vectorLength');
}
cosineDistance(other) {
return new FunctionExpression('cosine_distance', [this, vectorToExpr$1(other)], 'cosineDistance');
}
dotProduct(other) {
return new FunctionExpression('dot_product', [this, vectorToExpr$1(other)], 'dotProduct');
}
euclideanDistance(other) {
return new FunctionExpression('euclidean_distance', [this, vectorToExpr$1(other)], 'euclideanDistance');
}
/**
* @beta
* Creates an expression that interprets this expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC)
* and returns a timestamp.
*
* @example
* ```typescript
* // Interpret the 'microseconds' field as microseconds since epoch.
* field("microseconds").unixMicrosToTimestamp();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp.
*/
unixMicrosToTimestamp() {
return new FunctionExpression('unix_micros_to_timestamp', [this], 'unixMicrosToTimestamp');
}
/**
* @beta
* Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC).
*
* @example
* ```typescript
* // Convert the 'timestamp' field to microseconds since epoch.
* field("timestamp").timestampToUnixMicros();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of microseconds since epoch.
*/
timestampToUnixMicros() {
return new FunctionExpression('timestamp_to_unix_micros', [this], 'timestampToUnixMicros');
}
/**
* @beta
* Creates an expression that interprets this expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC)
* and returns a timestamp.
*
* @example
* ```typescript
* // Interpret the 'milliseconds' field as milliseconds since epoch.
* field("milliseconds").unixMillisToTimestamp();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp.
*/
unixMillisToTimestamp() {
return new FunctionExpression('unix_millis_to_timestamp', [this], 'unixMillisToTimestamp');
}
/**
* @beta
* Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC).
*
* @example
* ```typescript
* // Convert the 'timestamp' field to milliseconds since epoch.
* field("timestamp").timestampToUnixMillis();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of milliseconds since epoch.
*/
timestampToUnixMillis() {
return new FunctionExpression('timestamp_to_unix_millis', [this], 'timestampToUnixMillis');
}
/**
* @beta
* Creates an expression that interprets this expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC)
* and returns a timestamp.
*
* @example
* ```typescript
* // Interpret the 'seconds' field as seconds since epoch.
* field("seconds").unixSecondsToTimestamp();
* ```
*
* @returns A new {@link @firebase/firestore/pipelines#Expression} representing the timestamp.
*/
unixSecondsToTimestamp() {
return new FunctionExpression('unix_seconds_to_timestamp', [this], 'unixSecondsToTimestamp');
}
/**
* @beta
* Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC).
*
* @example
* ```typescript
* // Convert the 'timestamp' field to seconds since epoch.
* field("timestamp").timestampToUnixSeconds()