UNPKG

@firebase/firestore

Version:

The Cloud Firestore component of the Firebase JS SDK.

1,491 lines (1,487 loc) • 144 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var common948f0202_node = require('./common-60e0349e.node.cjs.js'); require('@firebase/app'); require('@firebase/util'); require('@firebase/webchannel-wrapper/bloom-blob'); require('@firebase/logger'); require('util'); require('crypto'); require('@grpc/grpc-js'); require('@grpc/proto-loader'); /** * @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 || common948f0202_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 (common948f0202_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 common948f0202_node.VectorValue) { return constant(value); } else if (Array.isArray(value)) { return constant(common948f0202_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 (common948f0202_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 common948f0202_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(); } 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 * 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 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 * 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 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 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(Function.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(Function.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(); * ``` * * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the number of seconds since epoch. */ timestampToUnixSeconds() { return new FunctionExpression('timestamp_to_unix_seconds', [this], 'timestampToUnixSeconds'); } timestampAdd(unit, amount) { return new FunctionExpression('timestamp_add', [this, valueToDefaultExpr$1(unit), valueToDefaultExpr$1(amount)], 'timestampAdd'); } timestampSubtract(unit, amount) { return new FunctionExpression('timestamp_subtract', [this, valueToDefaultExpr$1(unit), valueToDefaultExpr$1(amount)], 'timestampSubtract'); } /** * @beta * * Creates an expression that returns the document ID from a path. * * @example * ```typescript * // Get the document ID from a path. * field("__path__").documentId(); * ``` * * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the documentId operation. */ documentId() { return new FunctionExpression('document_id', [this], 'documentId'); } substring(position, length) { const positionExpr = valueToDefaultExpr$1(position); if (length === undefined) { return new FunctionExpression('substring', [this, positionExpr], 'substring'); } else { return new FunctionExpression('substring', [this, positionExpr, valueToDefaultExpr$1(length)], 'substring'); } } arrayGet(offset) { return new FunctionExpression('array_get', [this, valueToDefaultExpr$1(offset)], 'arrayGet'); } /** * @beta * * Creates an expression that checks if a given expression produces an error. * * @example * ```typescript * // Check if the result of a calculation is an error * field("title").arrayContains(1).isError(); * ``` * * @returns A new {@link @firebase/firestore/pipelines#BooleanExpression} representing the 'isError' check. */ isError() { return new FunctionExpression('is_error', [this], 'isError').asBoolean(); } ifError(catchValue) { const result = new FunctionExpression('if_error', [this, valueToDefaultExpr$1(catchValue)], 'ifError'); return catchValue instanceof BooleanExpression ? result.asBoolean() : result; } /** * @beta * * Creates an expression that returns `true` if the result of this expression * is absent. Otherwise, returns `false` even if the value is `null`. * * @example * ```typescript * // Check if the field `value` is absent. * field("value").isAbsent(); * @example * ``` * * @returns A new {@link @firebase/firestore/pipelines#BooleanExpression} representing the 'isAbsent' check. */ isAbsent() { return new FunctionExpression('is_absent', [this], 'isAbsent').asBoolean(); } mapRemove(stringExpr) { return new FunctionExpression('map_remove', [this, valueToDefaultExpr$1(stringExpr)], 'mapRemove'); } /** * @beta * * Creates an expression that merges multiple map values. * * @example * ``` * // Merges the map in the settings field with, a map literal, and a map in * // that is conditionally returned by another expression * field('settings').mapMerge({ enabled: true }, conditional(field('isAdmin'), { admin: true}, {}) * ``` * * @param secondMap - A required second map to merge. Represented as a literal or * an expression that returns a map. * @param otherMaps - Optional additional maps to merge. Each map is represented * as a literal or an expression that returns a map. * * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the 'mapMerge' operation. */ mapMerge(secondMap, ...otherMaps) { const secondMapExpr = valueToDefaultExpr$1(secondMap); const otherMapExprs = otherMaps.map(valueToDefaultExpr$1); return new FunctionExpression('map_merge', [this, secondMapExpr, ...otherMapExprs], 'mapMerge'); } pow(exponent) { return new FunctionExpression('pow', [this, valueToDefaultExpr$1(exponent)]); } round(decimalPlaces) { if (decimalPlaces === undefined) { return new FunctionExpression('round', [this]); } else { return new FunctionExpression('round', [this, valueToDefaultExpr$1(decimalPlaces)], 'round'); } } /** * @beta * Creates an expression that returns the collection ID from a path. * * @example * ```typescript * // Get the collection ID from a path. * field("__path__").collectionId(); * ``` * * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the collectionId operation. */ collectionId() { return new FunctionExpression('collection_id', [this]); } /** * @beta * Creates an expression that calculates the length of a string, array, map, vector, or bytes. * * @example * ```typescript * // Get the length of the 'name' field. * field("name").length(); * * // Get the number of items in the 'cart' array. * field("cart").length(); * ``` * * @returns A new `Expression` representing the length of the string, array, map, vector, or bytes. */ length() { return new FunctionExpression('length', [this]); } /** * @beta * Creates an expression that computes the natural logarithm of a numeric value. * * @example * ```typescript * // Compute the natural logarithm of the 'value' field. * field("value").ln(); * ``` * * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the natural logarithm of the numeric value. */ ln() { return new FunctionExpression('ln', [this]); } /** * @beta * Creates an expression that computes the square root of a numeric value. * * @example * ```typescript * // Compute the square root of the 'value' field. * field("value").sqrt(); * ``` * * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the square root of the numeric value. */ sqrt() { return new FunctionExpression('sqrt', [this]); } /** * @beta * Creates an expression that reverses a string. * * @example * ```typescript * // Reverse the value of the 'myString' field. * field("myString").stringReverse(); * ``` * * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the reversed string. */ stringReverse() { return new FunctionExpression('string_reverse', [this]); } ifAbsent(elseValueOrExpression) { return new FunctionExpression('if_absent', [this, valueToDefaultExpr$1(elseValueOrExpression)], 'ifAbsent'); } join(delimeterValueOrExpression) { return new FunctionExpression('join', [this, valueToDefaultExpr$1(delimeterValueOrExpression)], 'join'); } /** * @beta * Creates an expression that computes the base-10 logarithm of a numeric value. * * @example * ```typescript * // Compute the base-10 logarithm of the 'value' field. * field("value").log10(); * ``` * * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the base-10 logarithm of the numeric value. */ log10() { return new FunctionExpression('log10', [this]); } /** * @beta * Creates an expression that computes the sum of the elements in an array. * * @example * ```typescript * // Compute the sum of the elements in the 'scores' field. * field("scores").arraySum(); * ``` * * @returns A new {@link @firebase/firestore/pipelines#Expression} representing the sum of the elements in the array. */ arraySum() { return new FunctionExpression('sum', [this]); } split(delimiter) { return new FunctionExpression('split', [ this, valueToDefaultExpr$1(delimiter) ]); } timestampTruncate(granularity, timezone) { const internalGranularity = common948f0202_node.isString(granularity) ? granularity.toLowerCase() : granularity; const args = [this, valueToDefaultExpr$1(internalGranularity)]; if (timezone) { args.push(valueToDefaultExpr$1(timezone)); } return new FunctionExpression('timestamp_trunc', args); } /** * @beta * Creates an expression that returns the data type of this expression's result, as a string. * * @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]); } // TODO(new-expression): Add new expression method definitions above this line /** * @beta * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in ascending order based on this expression. * * @example * ```typescript * // Sort documents by the 'name' field in ascending order * pipeline().collection("users") * .sort(field("name").ascending()); * ``` * * @returns A new `Ordering` for ascending sorting. */ ascending() { return ascending(this); } /** * @beta * Creates an {@link @firebase/firestore/pipelines#Ordering} that sorts documents in descending order based on this expression. * * @example * ```typescript * // Sort documents by the 'createdAt' field in descending order * firestore.pipeline().collection("users") * .sort(field("createdAt").descending()); * ``` * * @returns A new `Ordering` for descending sorting. */ descending() { return descending(this); } /** * @beta * Assigns an alias to this expression. * * Aliases are useful for renaming fields in the output of a stage or for giving meaningful * names to calculated values. * * @example * ```typescript * // Calculate the total price and assign it the alias "totalPrice" and add it to the output. * firestore.pipeline().collection("items") * .addFields(field("price").multiply(field("quantity")).as("totalPrice")); * ``` * * @param name - The alias to assign to this expression. * @returns A new {@link @firebase/firestore/pipelines#AliasedExpression} that wraps this * expression and associates it with the provided alias. */ as(name) { return new AliasedExpression(this, name, 'as'); } } /** * @beta * * A class that represents an aggregate function. */ class AggregateFunction { constructor(name, params) { this.name = name; this.params = params; this.exprType = 'AggregateFunction'; this._protoValueType = 'ProtoValue'; } /** * @internal * @private */ static _create(name, params, methodName) { const af = new AggregateFunction(name, params); af._methodName = methodName; return af; } /** * @beta * Assigns an alias to this AggregateFunction. The alias specifies the name that * the aggregated value will have in the output document. * * @example * ```typescript * // Calculate the average price of all items and assign it the alias "averagePrice". * firestore.pipeline().collection("items") * .aggregate(field("price").average().as("averagePrice")); * ``` * * @param name - The alias to assign to this AggregateFunction. * @returns A new {@link @firebase/firestore/pipelines#AliasedAggregate} that wraps this * AggregateFunction and associates it with the provided alias. */ as(name) { return new AliasedAggregate(this, name, 'as'); } /** * @private * @internal */ _toProto(serializer) { return { functionValue: { name: this.name, args: this.params.map(p => p._toProto(serializer)) } }; } /** * @private * @internal */ _readUserData(context) { context = this._methodName ? context.contextWith({ methodName: this._methodName }) : context; this.params.forEach(expr => { return expr._readUserData(context); }); } } /** * @beta * * An AggregateFunction with alias. */ class AliasedAggregate { constructor(aggregate, alias, _methodName) { this.aggregate = aggregate; this.alias = alias; this._methodName = _methodName; } /** * @private * @internal */ _readUserData(context) { this.aggregate._readUserData(context); } } /** * @beta */ class AliasedExpression { constructor(expr, alias, _methodName) { this.expr = expr; this.alias = alias; this._methodName = _methodName; this.exprType = 'AliasedExpression'; this.selectable = true; } /** * @private * @internal */ _readUserData(context) { this.expr._readUserData(context); } } /** * @internal */ class ListOfExprs extends Expression { constructor(exprs, _methodName) { super(); this.exprs = exprs; this._methodName = _methodName; this.expressionType = 'ListOfExpressions'; } /** * @private * @internal */ _toProto(serializer) { return { arrayValue: { values: this.exprs.map(p => p._toProto(serializer)) } }; } /** * @private * @internal */ _readUserData(context) { this.exprs.forEach((expr) => expr._readUserData(context)); } } /** * @beta * * Represents a reference to a field in a Firestore document, or outputs of a {@link @firebase/firestore/pipelines#Pipeline} stage. * * <p>Field references are used to access document field values in expressions and to specify fields * for sorting, filtering, and projecting data in Firestore pipelines. * * <p>You can create a `Field` instance using the static {@link @firebase/firestore/pipelines#field} method: * * @example * ```typescript * // Create a Field instance for the 'name' field * const nameField = field("name"); * * // Create a Field instance for a nested field 'address.city' * const cityField = field("address.city"); * ``` */ class Field extends Expression { /** * @internal * @private * @hideconstructor * @param fieldPath */ constructor(fieldPath, _methodName) { super(); this.fieldPath = fieldPath; this._methodName = _methodName; this.expressionType = 'Field'; this.selectable = true; } get fieldName() { return this.fieldPath.canonicalString(); } get alias() { return this.fieldName; } get expr() { return this; } /** * @private * @internal */ _toProto(serializer) { return { fieldReferenceValue: this.fieldPath.canonicalString() }; } /** * @private * @internal */ _readUserData(context) { } } function field(nameOrPath) { return _field(nameOrPath, 'field'); } function _field(nameOrPath, methodName) { if (typeof nameOrPath === 'string') { if (common948f0202_node.DOCUMENT_KEY_NAME === nameOrPath) { return new Field(common948f0202_node.documentId()._internalPath, methodName); } return new Field(common948f0202_node.fieldPathFromArgument('field', nameOrPath), methodName); } else { return new Field(nameOrPath._internalPath, methodName); } } /** * @internal * * Represents a constant value that can be used in a Firestore pipeline expression. * * You can create a `Constant` instance using the static {@link @firebase/firestore/pipelines#field} method: * * @example * ```typescript * // Create a Constant instance for the number 10 * const ten = constant(10); * * // Create a Constant instance for the string "hello" * const hello = constant("hello"); * ``` */ class Constant extends Expression { /** * @private * @internal * @hideconstructor * @param value - The value of the constant. */ constructor(value, _methodName) { super(); this.value = value; this._methodName = _methodName; this.expressionType = 'Constant'; } /** * @private * @internal */ static _fromProto(value) { const result = new Constant(value, undefined); result._protoValue = value; return result; } /** * @private * @internal */ _toProto(_) { common948f0202_node.hardAssert(this._protoValue !== undefined, 0x00ed); return this._protoValue; } /** * @private * @internal */ _readUserData(context) { context = this._methodName ? context.contextWith({ methodName: this._methodName }) : context; if (isFirestoreValue(this._protoValue)) { return; } else { this._protoValue = common948f0202_node.parseData(this.value, context); } } } function constant(value) { return _constant(value, 'constant'); } /** * @internal * @private * @param value * @param methodName */ function _constant(value, methodName) { const c = new Constant(value, methodName); if (typeof value === 'boolean') { return new BooleanConstant(c); } else { return c; } } /** * Internal only * @internal * @private */ class MapValue extends Expression { constructor(plainObject, _methodName) { super(); this.plainObject = plainObje